coutが正しいサイズを示しているのに、printfがベクトルサイズに対して0を表示するのはなぜですか?

StackOverflow https://stackoverflow.com/questions/601180

  •  03-07-2019
  •  | 
  •  

質問

ベクターのサイズを取得するために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);

両方のフォーマット文字列が間違っています:

  1. answer%dに渡し、フォーマットを%lldにしていますが、unsigned long longを宣言しているため、%ldにする必要があります。

  2. 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;を動作させる可能性があります。

問題は、answerlong 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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top