質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Q&A

解決済

4回答

1913閲覧

C++でのNULL終端文字列の取り扱い

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

0グッド

1クリップ

投稿2017/11/26 16:48

編集2017/11/28 01:17

現在,C言語のプロジェクトをC++のプロジェクトとして書き換えています.詳細としては,ESP-8266というマイコンで,FreeOSというRTOSを使ってwi-fiのアクセスポイントへ接続し,ネットへ接続しようとしております.

サンプルプログラムでは,下記のようなプログラムが与えられており,WIFI_SSIDとWIFI_PASSを書き換えることで問題無く接続が可能となっております.しかし,ファイル名をmain.cからmain.cppへと変更すると,C++ 99 "ssid" outside aggregate initializerなどと表示され,コンパイルが通らない状況です.原因として,C99の機能であり,C++では用いることができないということがわかり,これを書き換えたいと考えております.

C

1 #define WIFI_SSID "hoge" 2 #define WIFI_PASS "piyo" 3 4 ~~~~~~ 5 中略 6 ~~~~~~ 7 8 struct sdk_station_config config = { 9 .ssid = WIFI_SSID, 10 .password = WIFI_PASS, 11 };

そこで,以下のようにプログラムを書換え,対処を行いました.コンパイルエラー自体はこれで回避することができたのですが,実際にプログラムを実行してみると,アクセスポイントの接続に失敗している状態となっており,文字列の取り扱いに問題があるのではないかと推測できる症状が発生しております.sdk_station_configが定義されているヘッダファイルには,NULL TERMINATED STRINGと書かれており,ヌル終端文字列(?)であるようなのですが,このような場合,どのように書き換えるのが適切なのでしょうか?

C++

1 #define WIFI_SSID "hoge" 2 #define WIFI_PASS "piyo" 3 4 ~~~~~~ 5 中略 6 ~~~~~~ 7 8 struct sdk_station_config config; 9 *(config.ssid) = WIFI_SSID; 10 *(config.password) = WIFI_PASS;

失礼いたしました.ご指摘いただきました,sdk_station_config構造体の定義を記載いたします.

C

1struct sdk_station_config { 2 uint8_t ssid[32]; /* Null terminated string */ 3 uint8_t password[64]; /* Null terminated string */ 4 uint8_t bssid_set; /* One if bssid is used, otherwise zero. */ 5 uint8_t bssid[6]; /* The BSSID bytes */ 6};

yohhoyさんよりご指摘いただきました,C++コンパイラのバージョンについて追記です.
以下,

$ gcc --version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/c++/4.2.1 Apple LLVM version 9.0.0 (clang-900.0.38) Target: x86_64-apple-darwin17.2.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

また,使用しているOSはOS X 10.13.1です.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KoichiSugiyama

2017/11/26 17:00

struct sdk_station_configの宣言部分も提示してください。そのほうがより正確な回答がつきやすいと思います。
退会済みユーザー

退会済みユーザー

2017/11/27 06:47

失礼いたしました.ご指摘いただきました,内容を追記いたしました.yohhoyさんにいただいたURLの記載と同じです.
yohhoy

2017/11/27 16:39

エラーメッセージから察するにC++コンパイラはGCCでしょうか?比較的古いバージョンと予想されますので、GCCバージョン(gcc --version出力結果など)も質問中に明記ください。
退会済みユーザー

退会済みユーザー

2017/11/28 01:17

ご指摘いただきました,C++コンパイラの情報を追記いたしました.
guest

回答4

0

こんにちは。

yohhoyさんが書かれている構造体定義の場合は、次の記述でできると思います。

C++

1#include <iostream> 2 3#define WIFI_SSID "hoge" 4#define WIFI_PASS "piyo" 5 6#ifdef __cplusplus 7extern "C" { 8#endif 9 10struct sdk_station_config { 11 uint8_t ssid[32]; /* Null terminated string */ 12 uint8_t password[64]; /* Null terminated string */ 13 uint8_t bssid_set; /* One if bssid is used, otherwise zero. */ 14 uint8_t bssid[6]; /* The BSSID bytes */ 15}; 16} 17 18int main() 19{ 20 struct sdk_station_config config={WIFI_SSID, WIFI_PASS, {}, {}}; 21 std::cout << config.ssid << "\n"; 22 std::cout << config.password << "\n"; 23}

他の方も書かれている通りこのような質問の場合、初期化したい変数の型(の関連部分)を正確に記載しないと正しい回答の難度が跳ね上がります。実は私は最初スルーしてました。yohhoyさんの補足依頼を見てちょっと回答してみたという経緯になります。
また、これが分かっていれば他の回答者様全員、恐らく正しい回答をされているだろうと思います。

投稿2017/11/27 02:30

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/27 07:24

失礼いたしました.詳細を追記いたしました.
Chironian

2017/11/27 07:54

えっと、それと同じ構造体を想定した回答をしていますが、これでは上手く行かないでしょうか? 上手く行かないようでしたら、どのように上手く行かないのか書いて頂けると回答できるかも知れません。
退会済みユーザー

退会済みユーザー

2017/11/27 15:16

ご回答ありがとうございます.失礼いたしました.実行結果について記載していたつもりが,しておりませんでした・・・ error: braces around scalar initializer for type 'uint8_t { aka unsigned char }' struct sdk_station_config config = {WIFI_SSID, WIFI_PASS, {}, {}}; ^ とコンパイルエラーとなってしまいます・・・
退会済みユーザー

退会済みユーザー

2017/11/27 15:17

済みません,ハットは一番最後の}の位置(セミコロンの前)です.
yohhoy

2017/11/27 16:45 編集

= {WIFI_SSID, WIFI_PASS, 0, {}}; で通るかもしれません。たぶん。
退会済みユーザー

退会済みユーザー

2017/11/28 01:50

ご指摘いただきました方法で通りました.質問へのコメントでもあげていただきましたが,その辺もコンパイラのバージョン依存なものなのですかね・・・?
yumetodo

2017/11/28 01:57 編集

というよりC++98としてコンパイルされているのでしょう。 https://wandbox.org/permlink/uj4PBb2BpUJTRjIu 日頃からC++11以降でコンパイルする(-std=c++11)ことを強く推奨します。 理由もないのに1998年とかいう太古の昔の物を使う必要はないです。現代に生きてください
退会済みユーザー

退会済みユーザー

2017/11/28 15:50

ご指摘の通りC++11でコンパイルできるよう引数渡すようmakeファイルに追記しました. C++は11,14,17が今あると思うのですがが,14以降ではなく11以降と書かれた意図はどういったところなのでしょうか・・・? また,コンパイラのバージョンは質問文に追記させていただきましたが,Clang-900.0.38です.
yumetodo

2017/12/03 05:54

Appleのカスタマイズが入ったgccってバージョン番号ほんとに意味不明で困る。少なくとも私には読めん。 あれって__GCC_MINOR__マクロの値とか当てになるんだろうか・・・ >C++は11,14,17が今あると思うのですがが,14以降ではなく11以降と書かれた意図はどういったところなのでしょうか・・・? そういうわけで14使えるのかわからなかったけど流石に11は使えるだろという思いで書きました
guest

0

ベストアンサー

構造体の初期化において、{}ブロックの中での「.変数 = 値」という書式は、C++では対応していませんのでエラーになります。C++での構造体の初期化は、Cの古典的な方法である定義したのと同じ順番で値だけを並べるか、構造体変数を定義した後でメンバ変数に一つ一つ代入していくか(下のコードのような具合ですね)、あるいはC++の機能として適切なコンストラクターを記述するかのいずれかになります。

ご質問で問題となっている下のコードは、*(~)としてしまっているので、メンバ変数ssidpasswordへの設定ではなく、そのポインタの指し示す領域に値を格納してしまっています。当然、それらのメンバ変数の初期化前なので、不正なアドレスへの書き込みになっています。

アスタリスクは不要(というか余計)なので取ってください。

C++

1struct sdk_station_config config; 2config.ssid = WIFI_SSID; 3config.password = WIFI_PASS;

追記
上記コードはssid,passwordをポインタと仮定したものなので、構造体の中でchar配列として定義しているならstrcpy等を使用してください。

投稿2017/11/27 01:24

編集2017/11/27 01:36
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/27 07:24

構造体の宣言では,unsigned char配列となっており,できればライブラリ側に手を加えることなく実装したいのですが,どのようにするのが良いのでしょうか.
yumetodo

2017/11/27 08:01

>造体の中でchar配列として定義しているならstrcpy等を使用してください。
退会済みユーザー

退会済みユーザー

2017/11/27 15:22

構造体の宣言ですが,unsigned char配列で行われており,以下のようなエラーとなってしまいます・・・ C++ /Volumes/esp-crosscompile/Projects/Test/http_get.cpp /Volumes/esp-crosscompile/Projects/Test/http_get.cpp: In function 'void http_get_task(void*)': /Volumes/esp-crosscompile/Projects/Test/http_get.cpp:29:9: warning: unused variable 'successes' [-Wunused-variable] int successes = 0, failures = 0; ^ /Volumes/esp-crosscompile/Projects/Test/http_get.cpp:29:24: warning: unused variable 'failures' [-Wunused-variable] int successes = 0, failures = 0; ^ /Volumes/esp-crosscompile/Projects/Test/http_get.cpp: In function 'void user_init()': /Volumes/esp-crosscompile/Projects/Test/http_get.cpp:121:34: error: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'char*' [-fpermissive] strcpy(config.ssid, WIFI_SSID); ^ In file included from ../../esp-open-rtos/libc/xtensa-lx106-elf/include/stdio.h:29:0, from ../../esp-open-rtos/lwip/include/arch/cc.h:47, from ../../esp-open-rtos/lwip/lwip/src/include/lwip/arch.h:43, from ../../esp-open-rtos/lwip/lwip/src/include/lwip/debug.h:35, from ../../esp-open-rtos/lwip/lwip/src/include/lwip/opt.h:46, from ../../esp-open-rtos/lwip/lwip/src/include/ipv4/lwip/ip_addr.h:35, from ../../esp-open-rtos/include/espressif/esp_misc.h:9, from ../../esp-open-rtos/include/espressif/esp_common.h:13, from /Volumes/esp-crosscompile/Projects/Test/http_get.cpp:7: ../../esp-open-rtos/libc/xtensa-lx106-elf/include/string.h:30:15: error: initializing argument 1 of 'char* strcpy(char*, const char*)' [-fpermissive] char *_EXFUN(strcpy,(char *__restrict, const char *__restrict)); ^ ../../esp-open-rtos/libc/xtensa-lx106-elf/include/_ansi.h:65:30: note: in definition of macro '_EXFUN' #define _EXFUN(name, proto) name proto ^ /Volumes/esp-crosscompile/Projects/Test/http_get.cpp:122:38: error: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'char*' [-fpermissive] strcpy(config.password, WIFI_PASS); ^ In file included from ../../esp-open-rtos/libc/xtensa-lx106-elf/include/stdio.h:29:0, from ../../esp-open-rtos/lwip/include/arch/cc.h:47, from ../../esp-open-rtos/lwip/lwip/src/include/lwip/arch.h:43, from ../../esp-open-rtos/lwip/lwip/src/include/lwip/debug.h:35, from ../../esp-open-rtos/lwip/lwip/src/include/lwip/opt.h:46, from ../../esp-open-rtos/lwip/lwip/src/include/ipv4/lwip/ip_addr.h:35, from ../../esp-open-rtos/include/espressif/esp_misc.h:9, from ../../esp-open-rtos/include/espressif/esp_common.h:13, from /Volumes/esp-crosscompile/Projects/Test/http_get.cpp:7: ../../esp-open-rtos/libc/xtensa-lx106-elf/include/string.h:30:15: error: initializing argument 1 of 'char* strcpy(char*, const char*)' [-fpermissive] char *_EXFUN(strcpy,(char *__restrict, const char *__restrict)); ^ ../../esp-open-rtos/libc/xtensa-lx106-elf/include/_ansi.h:65:30: note: in definition of macro '_EXFUN' #define _EXFUN(name, proto) name proto ^
yumetodo

2017/11/27 17:41

fpermissiveは今回はreinterpret_cast<char*>(config.ssid)していいです
catsforepaw

2017/11/28 01:04

yumetodoさん、フォローありがとうございます。 takano20771さん。「キャスト」は理解できますか? C言語には文字列型が存在しないので、文字列の扱いは「ライブラリー依存」となります。ご利用のライブラリーが文字の基本単位を`uint8_t`としている理由は判りませんが、利用する際はそれに合わせなければいけません。 基本的なことですが、移植作業は本来であれば当該言語の深い理解が必要とされるものです。言語リファレンス等の熟読をお勧めします。
退会済みユーザー

退会済みユーザー

2017/11/28 01:49

ご指摘ありがとうございます. キャストは既に試しておりましたが,コードにミスがあったようです. ご指摘頂きました通り,reinterpret_cast<char*>(config.ssid)で試したところ,うまく行きました. また,(char*)(config.ssid)としてもうまくいったので,おそらく昨日は(char*)config.ssidとでもかいていたのではないかと思います・・・・ catsforepawさんもありがとうございました.C++の理解を深める必要がありそうです・・・
yumetodo

2017/11/28 01:51

教訓: C形式のキャストを使うことなかれ
guest

0

構造体の定義が不明なので以下憶測です。

Cのコードで、
.ssid = WIFI_SSID
としているので、ssidはchar*なのではないでしょうか。
とすれば、C++の方では
config.ssid = WIFI_SSID;
と書けば良いように思えます。

投稿2017/11/27 00:11

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/27 07:22

構造体の定義を追記させていただきました.unsigned charの配列です.
guest

0

多分

cpp

1struct sdk_station_config config;

cpp

1sdk_station_config config{};

でいけると思いますが、KoichiSugiyamaさん指摘の通り追記お願いします。特に文字列をどう格納しているかや長さをどう見ているかを確認しておきたいので。

なおその初期化記法、一応C++標準化委員会に提案はされたんですけとねぇ・・・

投稿2017/11/26 17:06

編集2017/11/26 17:09
yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/27 07:21

実装自体はそんなに難しい物では無いと思うのですが,何か競合するような機能があるのでしょうか・・・?
yumetodo

2017/11/27 08:00

どうせその初期化が使える要件の定義とPODという概念を消すみたいな話らへんが衝突していただけだと邪推(多分違う
退会済みユーザー

退会済みユーザー

2017/11/27 15:25

なるほど.言語体系が複雑なC++ならではといったところなのでしょうか. 補足ありがとうございます.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問