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

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

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

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

C++

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

Q&A

2回答

4652閲覧

C++でC言語の関数を利用する時

strike1217

総合スコア651

C

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

C++

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

0グッド

1クリップ

投稿2018/07/07 15:53

C++でC言語の関数を利用する時って結構ありますか??
自分は、Linux系のプログラミングをしていると良くあります。

例えば・・・printf関数とかは結構使いますかね。
C++でC言語の関数を利用していると困ることが時々あります。

STLとC言語関数の連携と型についてです。
2016年、C言語はどう書くべきか (前編)

新しいコードに、char、int、short、long、unsignedなどの型を使おうとしているなら、それは誤りです。

charはもう使わないので注意してください。実際、C言語ではcharは誤った名称で誤った使い方をされています。

C++

1 std::string text = "Hello!!"; 2 std::cout << text << std::endl; 3 std::printf("%s\n", text.c_str());

std::stringのc_str()関数ってchar型のポインタですよね。
char使ってるんですが・・・こういうのはどうするんでしょう??

「std::coutを使いたくない」という方は結構いるのではないでしょうか?
STLと連携を取るなら、std::coutの方が良さそうですが・・・
自分は、printfの方が使いやすいですね。

他にも、最近問題となったのが、mmap()とstd::fstream との連携ができなく結局fopen関数を使う羽目に・・・・なったり

ん〜〜〜。

正直C++でC言語の関数を使わない方が良いんでしょうか??
しかし、C言語の大量の関数群をC++でも使いたい!からC言語の上位互換として開発したものなんですよね?
使えないとC言語の上位互換という位置づけでは無くなりそうですね。

関数のパラメータ用にSTLコンテナから要素を取り出し、いちいち型を変換しなくてはいけないのが、かなり面倒です。

皆さんはどのようにして問題を回避しているのでしょうか?
ぜひ教えてください。

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

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

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

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

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

guest

回答2

0

回答

それは元記事の内容をだいぶ歪めた理解と言うことができます(元記事のミスリードもひどいけど)。

新しいコードに、char、int、short、long、unsignedなどの型を使おうとしているなら、それは誤りです。

とは 整数を格納する型として と捉えるべきです。文字列、ただし一単位が1byteな文字エンコードを格納する型としては、これまで通りchar型を用いるべきです。


文字列についてはC11/C++11にてUnicode周りの大きな改善(不十分)が追加されたことを知っておくべきです。

まずこれまで

文字リテラル格納される物
''char実装依存
L''wchar_t実装依存(一文字を表すのに十分な大きさの型とあるが、これは実現不可能、UTF-16かUTF-32が現実には使われる

がありましたが、Unicode対応のため

文字リテラル格納される物
u''char16_tUTF-16
U''char32_tUTF-32

が追加されました。同様に文字列リテラルも存在します。

文字列リテラルに限ってはC11/C++11で

文字列リテラル格納される物
u8""const char[]UTF-8

が追加されています。

またC++17では

文字リテラル格納される物
u8''charUTF-8

が追加されています(C言語でどうだったか覚えてない)

ここで重要なこととして、C/C++にはなんとまさかのUTF-8を保証する型が存在しません。

https://cpplover.blogspot.com/2016/09/c-p0370r1-p0379r0.html
C++11のときにchar8_tが必要だと訴えたら、charは古典的にバイト列を表現する型なので十分だ。char型以外の型があるのは混乱する。などと理解のないUnicodeの世界に生きていない名だたる委員達から散々に批判された。その委員達も、今では、「やっぱりchar8_tがないのは失敗だったなぁ」とぼやいている。それ見たことか。

C++11で文字の何たるかを理解できないアスキー文字しか解さないクソどもがUTF-8を保証するchar8_t型をRejectしたからです。

C++17で再び提案されるもやはりReject。

C/C++標準化委員会の連中は全く文字の何たるかを理解できないと言うことができます。

さて、C++20に向けて再びchar8_t型が提案されています

もしchar8_t型が標準入りしたならば、もはやcharは使うべきではないと言えるでしょう。


整数型について、stdint.h/cstdintヘッダーに定義されるintN_t型を用いよ、という主張は正しいと言えなくもないです。大きさが明確に定まっているべきbinary formatに対応する構造体/trivialy copyable classの要素型であるとか、他の言語から使われることを想定するC APIなどは必ずこれを用いるべきです。またそうでない場合も2の補数系を仮定できるとか1byte=8bitを仮定できるなど考えうことが減り、たかが差の絶対値を計算するのに
C/C++はnull安全になる前に安全に差の絶対値を計算できるようになるべきではないか - Qiita#つまり安全に差の絶対値を計算できるようにはどうすればいいのか
のようなコードを書かずに済んだりと恩恵があります。


話がそれました。戻しましょう。

正直C++でC言語の関数を使わない方が良いんでしょうか??

C++に便利な関数群が十分存在していてそのほうが楽だからそちらを使う、ただそれだけのことです。

ご自分でも

関数のパラメータ用にSTLコンテナから要素を取り出し、いちいち型を変換しなくてはいけないのが、かなり面倒です。

と書かれているじゃないですか。プログラマーは怠惰であるべきなので、STLを使うほうが楽できます。STLの関数群/クラス群の使い方を調べるには
https://cpprefjp.github.io/
が便利です(宣伝)

ただしiostream系はC++のstd::coutのようなスタイルやCのprintfのようなスタイルともに明らかな問題が存在し、fmtlib/fmtとかを使うべきだということができます。またlocaleはだいたいC/C++問わずぶっ壊れていて使い物になりません

以下余談。

std::stringのc_str()関数ってchar型のポインタですよね。

違います。const修飾されている=const char *です。C++はconst性についてかなり厳密に扱います。


C/C++にはUnicodeどうしの文字コード変換を行う方法が存在しないという状態が生じています(C++11で入ったが致命的な欠陥が見つかってC++17でdeprecated)


C APIで文字列を受け取る場合のAPI設計について留意するべきことがあります。

Cだけやっていると

c

1void foo(char* str);

のようなAPIを作りがちですが、2つの点からこれをするべきではありません。

  1. 文字列の長さがNULL終端文字に依存している

Cでは文字列とはNULL終端するbyte列のことでしたが、これはプログラミングをする上で余計なメモリ確保を強いる事があり、非効率的です。
C++ですらC++17でstring_viewなるものが追加され、文字列の先頭へのポインタと長さの構造体のようなクラスをstd::stringと同じインターフェースで扱えるようになったことでNULL終端しない文字列を扱う機会が増えます。

  1. const修飾されていない

const修飾されていないとC++ではこのAPIに文字列リテラルを渡すことができません。
また文字列が書き換えられる可能性があるため安全のために一度動的メモリ確保を行いコピーするコストが発生し、著しく実行速度に影響を与えます。

したがって

c

1void foo(const char* str, size_t len);

のようにしましょう。

投稿2018/07/07 16:29

編集2018/07/07 16:51
yumetodo

総合スコア5850

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

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

Chironian

2018/07/07 17:19

おお、UTF-8を保証する型が粘り強く提案されているのですね!! 頑張れ! char8_t。 u8""の文字の型がchar8_tになるのも嬉しいですね。 ついでに u8string u8str=u16string(L"xyz"); などもできるようになると嬉しいけど、提案はされてないっぽい?(operator=をフリー関数で定義できないから、厳しそうな気がする。)
yumetodo

2018/07/08 01:54

std::codecvtの特殊化は同文章で提案されてるんですけどねぇ・・・。Unicode同士の変換は提案されてないと思いますが、filesystemみたいなbreaking changeを要求するクソ仕様を無理やり入れるんじゃなくてchar8_tを入れるのが先でしょうね。
strike1217

2018/07/08 05:55

yumetodo様はC言語の関数をC++で利用する場面ってあるんでしょうか? ほとんどないですかね?
yumetodo

2018/07/08 13:26 編集

私はライブラリを作って遊んでいる人間なので、template対応させるのが面倒なC標準の関数は呼ばないですね・・・。例えば文字列操作はCの関数ではなくstd::char_trais以下の関数のほうがtemplate対応しやすいです。ただしC++20がまだ来ないのでカレンダー周りやるときはtm構造体などは触りますがChironianさん指摘の通りそうとうだるい・・・。 C APIな外部ライブラリは普通に使いますよ。 標準入出力についてはCで正しく標準入出力を扱うのはC++のtemplateでメタプログラミングするよりも難しいので自分には無理です、というかあれは人間には無理。
yumetodo

2018/07/08 13:33

printfが恋しくなったらそうじゃなくってfmtlib/fmtを検討してみてください。圧倒的に恋に落ちる。私が本当に欲しかったもの感ある。
strike1217

2018/07/24 10:15

C++ Now and Tomorrow というものがあるんですか! 初めて知りました。 素晴らしいですね!
yumetodo

2018/10/26 12:05

その後どうでしょうか?
strike1217

2018/10/30 00:25

webのサーバークライアントを作成してみたのですが、微妙ですね。 やはり、C言語はC言語。C++はC++と言ったところでしょうか。 ネットワーク系プログラミングでは、C言語の関数を使わなくてはならないので、C++のコンテナや関数との相性と言いますと微妙です。 いちいち型を変換するのが面倒なので、あまりC++の関数やコンテナを使用していない状態ですね。 あ!でも、クラスとかconstexprとかは使えるので、まぁやはりC++の便利感がありますね。 Better Cとして利用できる程度でしょうか。
yumetodo

2018/10/30 05:25

boost.asioも絶妙に使いにくいし、そうなりますよねぇ・・・
strike1217

2018/10/30 05:43

ええ・・・ 困ったものですね。 C++20 で確かネットワーク関連が追加されるんでしたっけ。 ネットワーク系のプログラミングは、まぁそちらの方に期待するしかないですかね。
guest

0

こんにちは。

そのリンク先は結構話題になります
内容については玉石混淆って感じですね。あまり気にしない方が良いかも知れません。

正直C++でC言語の関数を使わない方が良いんでしょうか??

同様な機能があるものについてはC++を使った方が生産性は上がり易いです。しかし、当然学習コストがかかるので悩ましい部分はあります。

私もずいぶん長い間printf系を使ってました。
でも、iostreamに慣れた今は勿体無いかったと感じます。ログ・ツールをvsnprintfで無茶苦茶苦労して作ってましたが、std::stringstreamなら超簡単ですし。
整形出力を頻繁に使うなら、boost::formatは便利ですよ。%演算子がちょっと鬱陶しいですけどね。

また、カレンダー系は未だサポートされていませんのでC言語の関数を未だに使うしかないです。(マルチスレッド対応版は、gccとmsvcと標準規格の全てが異なっているのでマジ頭痛かったですが、背に腹は変えられません。)
C++2aでやっとサポートの見込みのようです。ダメダメだったカレンダーがまともになりそうですけど、<chrono>使い方が難しいのが難点です。

投稿2018/07/07 17:07

編集2018/07/07 17:23
Chironian

総合スコア23272

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

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

yumetodo

2018/07/08 01:59 編集

><chrono>は使い方が難しい 今は慣れたし論理的でわかりやすいと感じるけど、勉強してた頃は江添さんの解説記事をにらめっこしながら書いてたなぁ・・・。 ただC++11で入ったchronoのtime_pointとdurationの分離はRustでもそうだし、C++固有の概念でもないので、ぜひとも身につけたいところ。
strike1217

2018/07/08 05:51

C言語の関数を利用する場面というのはほとんどないんですか?
Chironian

2018/07/08 06:31

まだベターCとしてC++を使っていた頃は頻繁に使ってましたよ。 C言語に比べると設計が新しい分よく練り込まれているので、C++を真面目に勉強し始めてからはC++のライブラリを使うことが増えました。(とは言っても既に古臭くなっているものも残ってます。特にiostream。更新されることを祈ってます。)
strike1217

2018/07/08 09:11

C++はC言語の機能受け継ぐ必要性ってあったんですか? 新たにC++用の関数を作るならC言語の機能いらなくないですよね? C言語とは分けて考えるべきですかね。
Chironian

2018/07/08 09:41

> C++はC言語の機能受け継ぐ必要性ってあったんですか? ありますよ。互換性は非常に重要ですから。 また、C++のライブラリの使い方が難しいことはご存知の通りと思います。 Cライブラリを一切使えなくしたら、C++のライブラリの使い方をある程度悟るまでC++を使えません。 それよりは、Cライブラリも使えるようにしておき、少しづつでも悟った機能から使えばよいというのはたいへんありがたいですよ。
strike1217

2018/07/08 11:43

ああ!なるほど!そういう考え方ですか!
yumetodo

2018/07/08 13:30

> C++はC言語の機能受け継ぐ必要性ってあったんですか? FFIをC++に持ってきて互換を切ってしまったらもはやC++に存在価値がないですね、それくらいならRust使う。 C標準ライブラリはC++的にはどうでもいいですが、Cのコア言語機能は負の側面があるにもかかわらず維持しなければならない絶対ラインです。
strike1217

2018/07/08 13:34 編集

「FFIをC++に持ってきて互換を切ってしまったらもはやC++に存在価値がない」 なるほど。重要なのはライブラリの方ではないんですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問