Jump to content

help: what does this warning mean?

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
46 replies to this topic

#1
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts
language- c
os- ubuntu
cc 4.3.3

i was compiling following program

#include<stdio.h>
main(){
char a[]="helio",b[]="howdiee",c[]="hello";
printf("%u\n",a);
printf("%u\n",&b[0]);
printf("%u\n",&c[0]);
}

but i keep on getting the following warning

arraytest.c: In function ‘main’:
arraytest.c:4: warning: format ‘%u’ expects type ‘unsigned int’, but argument 2 has type ‘char *’
arraytest.c:5: warning: format ‘%u’ expects type ‘unsigned int’, but argument 2 has type ‘char *’
arraytest.c:6: warning: format ‘%u’ expects type ‘unsigned int’, but argument 2 has type ‘char *’

what does this warning mean and how do i deal with it???

#2
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts
Change the %u to %s on the first printf call and to %c on the second and third. You're passing characters and then telling printf that you're passing in unsigned integers.

You'll want to take a look at this:
printf() Reference

You also need to get rid of the ampersands on b and c. There's only one special case where you should ever have to do that in a call to printf. I think you're confusing printf with scanf - scanf requires the ampersand on all arguments except when passing arrays.

#include <stdio.h>

int main(void) {
    char a[] = "helio", b[] = "howdiee", c[] = "hello";

    printf("%s", a);
    printf("%c", b[0]);
    printf("%c", *c);  //another way of doing the same thing

    return 0;
}

(Anal-retentive note: main should always return an int.)

Edited by dargueta, 15 August 2009 - 08:19 AM.
Provided sample code

sudo rm -rf /

#3
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts
the problem is that i want to print the starting addresses of the three arrays. even with the warnings if i go ahead and execute the program i get the ouput. i just want to know how to get rid of the warnings.
when i use %p in the format specifiers instead of %u , no warnings pop up and i also get the addresses printed but the addresses get printed in hexadecimal form. i want to print the addresses in decimal without getting the warnings.

#4
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts

dargueta said:

Change the %u to %s on the first printf call and to %c on the second and third. You're passing characters and then telling printf that you're passing in unsigned integers.


You also need to get rid of the ampersands on b and c. There's only one special case where you should ever have to do that in a call to printf. I think you're confusing printf with scanf - scanf requires the ampersand on all arguments except when passing arrays.


#include <stdio.h>


int main(void) {

    char a[] = "helio", b[] = "howdiee", c[] = "hello";


    printf("%s", a);

    printf("%c", b[0]);

    printf("%c", *c);  //another way of doing the same thing


    return 0;

}


(Anal-retentive note: main should always return an int.)

the problem is that i want to print the starting addresses of the three arrays. even with the warnings if i go ahead and execute the program i get the ouput. i just want to know how to get rid of the warnings.
when i use %p in the format specifiers instead of %u , no warnings pop up and i also get the addresses printed but the addresses get printed in hexadecimal form. i want to print the addresses in decimal without getting the warnings.

#5
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts
Use a typecast to an unsigned long long.

printf("%llu\n", (unsigned long long)b);

or

printf("%llu\n", (unsigned long long)&b[0]);

Just curious - why do you need decimal instead of hex? Hex is easier to read and far easier to tell byte & page alignment.

Edited by dargueta, 15 August 2009 - 08:49 AM.
Added example

sudo rm -rf /

#6
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts

dargueta said:

Use a typecast to an unsigned long long.


printf("%llu\n", (unsigned long long)b);


or


printf("%llu\n", (unsigned long long)&b[0]);


Just curious - why do you need decimal instead of hex? Hex is easier to read and far easier to tell byte & page alignment.

though using %llu with type cast gives a whole new warning, using %lu or %u with typecast works fine without any warnings.

#7
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts
At the very least use %lu. %u could (probably would) truncate the pointer on a 64-bit system. What warning do you get?
sudo rm -rf /

#8
csepraveenkumar

csepraveenkumar

    Learning Programmer

  • Members
  • PipPipPip
  • 52 posts

dargueta said:

At the very least use %lu. %u could (probably would) truncate the pointer on a 64-bit system. What warning do you get?

warning: cast from pointer to integer of different size

#9
dcs

dcs

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 775 posts

csepraveenkumar said:

when i use %p in the format specifiers instead of %u , no warnings pop up and i also get the addresses printed but the addresses get printed in hexadecimal form. i want to print the addresses in decimal without getting the warnings.
My recommendation would be to use the correct specifier %p and teach yourself to become more comfortable with the hexadecimal form.

#10
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts

Quote

why should i need to use typecast at all. all i want to do is read the contents of the pointer to the array. the original function works just fine in turbo c.

1) If you don't typecast, printf() will expect the wrong number of bytes for its arguments. You'll get garbage as output, and if you're really unlucky you'll corrupt the stack. Trust me, I've done it before.
2) Turbo C is notorious for doing nonstandard and weird things. Just because the compiler doesn't warn you that you're doing something unsafe doesn't mean that it's not unsafe. Use GCC, and be sure to compile with the -Wall flag. Better safe than sorry.
3) I agree with dcs, hex is far better for several reasons:
- You can tell what bits are set and can mask easily.
- You can tell if the address is aligned on, say, a 4K boundary--useful for paging, shared memory, etc.
- Fewer digits
- Corresponds nicely with the binary representation; one hex digit is exactly four bits,
whereas a decimal digit is like three and a half.
- Just about everyone else uses hex addresses. (Some occasionally use octal, but
that's old and more cumbersome because an octal digit is 3 bits.)
sudo rm -rf /

#11
Mathematix

Mathematix

    Programmer

  • Members
  • PipPipPipPip
  • 112 posts

csepraveenkumar said:

the problem is that i want to print the starting addresses of the three arrays. even with the warnings if i go ahead and execute the program i get the ouput. i just want to know how to get rid of the warnings.
when i use %p in the format specifiers instead of %u , no warnings pop up and i also get the addresses printed but the addresses get printed in hexadecimal form. i want to print the addresses in decimal without getting the warnings.
Is this what you're after?

#include <stdio.h>
#include <stdlib.h>

int main()
{
	char* wurdzPtr;
	char wurdz[] = "These are the words in my char array.";

	wurdzPtr = (char *)malloc(sizeof(wurdz)/sizeof(wurdz[0]));

	wurdzPtr = wurdz;

	printf("\'wurdz\' contains \'%s\' at address 0x%x.\n", wurdz, wurdz);
	printf("\'wurdz\' contains \'%s\' at address %d.\n", wurdz, wurdz);  // In decimal
	printf("\'wurdzPtr\' contains \'%s\' at address 0x%x.\n", wurdzPtr, wurdzPtr);
	printf("\'wurdzPtr\' contains \'%s\' at address %d.\n", wurdzPtr, wurdzPtr); // In decimal

	return 0;
}
'%x' will print a hex value - in this case the address of the array.

#12
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts
printf("\'wurdz\' contains \'%s\' at address 0x%x.\n", wurdz, wurdz);

No. Don't ever do that. You're assuming a pointer is the same size as an integer, which is a very bad assumption to make. At the very least typecast the pointer to an integer, but you might be truncating the pointer if you do that. See my previous post in this thread about typecasting and stack corruption.

printf("\'wurdz\' contains \'%s\' at address %#08x.\n", wurdz, (unsigned int)wurdz);

This may work on a 32-bit system, but is likely to fail or do unexpected things on a 64-bit system; hence my suggestion to typecast to an unsigned long long, as it's required to be at least 64 bits.

EDIT: Just noticed this:

wurdzPtr = wurdz;

These are not C++ strings. You're orphaning a block of memory here, not assigning wurdzPtr to contain the same characters as wurdz. What this does is make wurdzPtr point to wurdz, leaving whatever memory wurdzPtr pointed to before just floating in memory with nothing to reference it...which means you can't free it. Memory leak. (And though the system will reclaim the memory in this example, you should always free what you allocate.)

Edited by dargueta, 16 August 2009 - 06:10 AM.
Found error

sudo rm -rf /