Question

I don't get why I get 0 when I use printf and %d to get the size of my vector:

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 iterate through the vector via

if(i=0;i<sieve.size();i++) 

I get the correct number of iterations.

What am I doing wrong or what is up with printf? size() returns an int right??


Here's my entire little script:

#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;
}
Was it helpful?

Solution

Now, with the complete source, it is clear.

You declared:

int size;

Then you used:

std::printf("current last: %d sieve size: %ld\n", answer, size);
std::printf("Limit: %d Answer: %d sieve size: %ld\n", limit, answer, size);

If size is int, you should use "%d", not "%ld". A good compiler would have warned you about this. GCC gives these warnings for your original version:

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’

This tells a lot.

You should declare size as:

std::vector<long long>::size_type size;

Then you should use it as:

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);

Of course, using iostream avoids you these problems, specially the ugly casting in printf() to transform size to a type known to printf.

OTHER TIPS

This is screwing up because you've got:

unsigned long long answer = 0;
int size;

and you call printf with:

std::printf("current last: %d sieve size: %ld\n", answer, size);

Both of your format strings are wrong:

  1. You're passing answer to printf and formatting it %d, but it should be %lld, since it's declared unsigned long long.

  2. You're passing size with %d instead of %ld. Since size is and int, it should be %d.

When those args get passed to printf, it's printing the first 32 bits of answer for the first %d and the second 32 bits (or more, past the end!) of answer for the %ld. This is not what you want.

If you compile with -Wall your compiler should warn you about this kind of thing. Pay very close attention to the warnings!

Looks crazy. Because size is declared as "int size", printf("...%d") is definitely correct. It can't be about size_t being different than "int" in size, because you explicitly declare "size" as int, and cout << ... size ... works correctly.

Have you checked that you have included ? It might be that without proper declaration on your system printf works "wrong".

Your problem is that answer is defined as a long long and you only printf it with a %d.

printf is a varargs function and in C that means the compiler doesn't know what arguments you passed into the function. It cannot do its normal type conversions and it has to trust its user to get the format arguments right, or the arguments will not be pulled off the call stack properly.

You didn't get it right.

vector sizes are size_t, which I believe is usually a long...

Couldn't say why printf isn't working, though.

The size() method returns size_t, which depends on your c++ implementation. When you try to printf("%d"), you're telling the library to expect an int, which isn't necessarily the case; it then takes an int from the call stack, which is taking only the high-order bytes of the size_t.

What you'll need to do is force the return value size() to a known data type with casting: printf("%d", (int) size)

What's the hardware you're running on? Odds are that size is a different type than you think. Print sizeof(size) and check, or try a %ld. If you have a big-endian machine like a PPC, size is a long, and you print a %d, you get the all-zeros end of the long.

update

Okay, this is what I get with an 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
$ 

You probably should start breaking the code up into smaller pieces and trying them; there's something hinky here.

This will work:

std::printf("current last: %**lld** sieve size: %ld\n", answer, size);

The problem is that answer is a long long (a 64 bit integer) and %d expects a 32bit integer. So size doesn't get printed. You will need to use %lld.

For more information on format strings for printf check out: http://en.wikipedia.org/wiki/Printf

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top