why does printf show a 0 for vector size when cout shows the correct size?
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;
}
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:
You're passing
answer
toprintf
and formatting it%d
, but it should be%lld
, since it's declaredunsigned long long
.You're passing size with
%d
instead of%ld
. Sincesize
is andint
, 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