coutが正しいサイズを示しているのに、printfがベクトルサイズに対して0を表示するのはなぜですか?
質問
ベクターのサイズを取得するためにprintfと%dを使用すると0になる理由がわかりません:
vector<long long> sieve;
int size;
...
//add stuff to vector
...
size = sieve.size();
printf("printf sieve size: %d \n", size); //prints "printf sieve size: 0"
std::cout << "cout sieve size: ";
std::cout << size;
std::cout << " \n ";
//prints "cout sieve size: 5 (or whatever the correct sieve size is)"
を介してベクトルを反復処理する場合
if(i=0;i<sieve.size();i++)
正しい反復回数を取得します。
何が間違っているのですか、printfで何が起きているのですか? size()はintを返しますか?
これが私の小さなスクリプト全体です:
#include <iostream>
#include <vector>
#include <stack>
#include <math.h>
int main (int argc, char * const argv[]) {
unsigned long long answer = 0;
unsigned long long cur = 2;
std::vector<long long> sieve;
unsigned long long limit;
unsigned long long value;
unsigned int i;
int size;
bool isPrime;
std::cout << "Provide a value to find its largest prime factor: ";
std::cin >> value;
limit = ceil(sqrt(value));
sieve.push_back(2);
while(cur++ < limit){
isPrime = true;
sieve.begin();
for(i=0; i<sieve.size();i++){
if(!(cur % sieve[i])){
isPrime = false;
break;
}
}
if(isPrime){
if(!(value % cur)){
std::printf("Is prime factor: %d\n", cur);
sieve.push_back(cur);
answer = sieve[sieve.size() - 1];
size = sieve.size();
std::printf("current last: %d sieve size: %ld\n", answer, size);
for(i=0; i<sieve.size();i++){
std::printf("sieve iter: %d sieve val: %d\n", i, sieve[i]);
std::cout << size;
std::cout << " wtf\n";
}
}
}
}
answer = sieve[sieve.size() - 1];
size = sieve.size();
std::printf("Limit: %d Answer: %d sieve size: %ld\n", limit, answer, size);
return 0;
}
解決
今、完全なソースで、それは明らかです。
宣言しました:
int size;
次に使用したもの:
std::printf("current last: %d sieve size: %ld\n", answer, size);
std::printf("Limit: %d Answer: %d sieve size: %ld\n", limit, answer, size);
サイズがintの場合、<!> quot;%ld <!> quot;ではなく、<!> quot;%d <!> quot;を使用する必要があります。これについては、優れたコンパイラーが警告しているはずです。 GCCは元のバージョンに対して次の警告を表示します。
test.cpp: In function ‘int main(int, char* const*)’:
test.cpp:17: warning: converting to ‘long long unsigned int’ from ‘double’
test.cpp:30: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:34: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:34: warning: format ‘%ld’ expects type ‘long int’, but argument 3 has type ‘int’
test.cpp:36: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long long int’
test.cpp:45: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:45: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long long unsigned int’
test.cpp:45: warning: format ‘%ld’ expects type ‘long int’, but argument 4 has type ‘int’
これは多くを物語っています。
次のようにサイズを宣言する必要があります:
std::vector<long long>::size_type size;
次に、次のように使用する必要があります。
std::printf("current last: %llu sieve size: %llu\n", (unsigned long long) answer, (unsigned long long) size);
std::printf("Limit: %llu Answer: %llu sieve size: %llu\n", (unsigned long long) limit, (unsigned long long) answer, (unsigned long long) size);
もちろん、iostreamを使用すると、これらの問題を回避できます。特に、printf()のいキャストにより、サイズをprintfに既知の型に変換できます。
他のヒント
あなたが持っているのでこれは台無しです:
unsigned long long answer = 0;
int size;
そしてprintf
を次のように呼び出します:
std::printf("current last: %d sieve size: %ld\n", answer, size);
両方のフォーマット文字列が間違っています:
-
answer
を%d
に渡し、フォーマットを%lld
にしていますが、unsigned long long
を宣言しているため、%ld
にする必要があります。 -
size
ではなくint
でサイズを渡します。-Wall
は<=>であるため、<=>でなければなりません。
これらの引数がprintfに渡されると、最初の<=>には<=>の最初の32ビットが、<=>には<=>の2番目の32ビット(またはそれ以上、終わりを超えて!) 。これはあなたが望むものではありませんではありません。
<=>でコンパイルする場合、コンパイラはこの種のことについて警告する必要があります。警告に細心の注意を払ってください!
おかしく見えます。サイズは<!> quot; int size <!> quot;として宣言されているため、printf(<!> quot; ...%d <!> quot;)は間違いなく正しいです。 size_tが<!> quot; int <!> quotと異なることはありません。サイズで、<!> quot; size <!> quot;を明示的に宣言するためint、およびcout <!> lt; <!> lt; ...サイズ...正しく動作します。
含まれていることを確認しましたか?システム上で適切な宣言がなければ、printfは<!> quot; wrong <!> quot;を動作させる可能性があります。
問題は、answer
がlong long
として定義されており、%d
でのみprintfすることです。
printfはvarargs関数であり、Cでは、コンパイラーが関数に渡した引数をわからないことを意味します。通常の型変換を行うことはできず、フォーマット引数を正しく取得するにはユーザーを信頼する必要があります。そうしないと、引数がコールスタックから適切に取り出されません。
正しくありませんでした。
ベクトルサイズはsize_t
で、通常はlong
...
ただし、printf
が機能しない理由を説明できませんでした。
size()
メソッドはsize_t
を返しますが、これはc ++実装に依存します。 printf("%d")
をしようとすると、ライブラリにint
を期待するように指示しますが、必ずしもそうではありません。次に、コールスタックからprintf("%d", (int) size)
を取得します。これは、<=>の上位バイトのみを取得しています。
行う必要があるのは、キャストを使用して既知のデータ型に戻り値<=>を強制することです。 <=>
実行しているハードウェアは何ですか?オッズは、size
があなたが思っているものとは異なるタイプだということです。 sizeof(size)
を印刷して確認するか、%ld
を試してください。 PPCのようなビッグエンディアンのマシンを使用している場合、サイズはlong
で、%d
を印刷すると、すべてがゼロのロングエンドになります。
更新
さて、これはIntel Mac mini 10.5で得られるものです:
$ cat trySize.C
#include <iostream>
#include <vector>
int main(){
std::cout << "sizeof(size_t): "
<< sizeof(size_t)
<< std::endl ;
std::vector<long long> sieve ;
std::cout << "sizeof(sieve.size()): "
<< sizeof(sieve.size())
<< std::endl;
printf("sizeof(sieve.size()) (printf): %d\n", sizeof(sieve.size()));
return 0;
}
$ g++ trySize.C
$ ./a.out
sizeof(size_t): 4
sizeof(sieve.size()): 4
sizeof(sieve.size()) (printf): 4
$
おそらく、コードを小さな断片に分割して、試してみる必要があります。ここには何か奇妙なことがあります。
これは動作します:
std::printf("current last: %**lld** sieve size: %ld\n", answer, size);
問題は、答えがlong long(64ビット整数)であり、%dが32ビット整数を想定していることです。したがって、サイズは印刷されません。 %lldを使用する必要があります。
printfのフォーマット文字列の詳細については、以下をご覧ください。 http://en.wikipedia.org/wiki/Printf