[vox-tech] C - passing chars and pointer to chars

Peter Jay Salzman p at dirac.org
Fri Jun 2 10:27:04 PDT 2006


Hi Mike,

It appears to be a gcc4 thing.  Happens even with no warnings switched on.

Doesn't appear to happen at all with gcc3.

Pete




On Fri 02 Jun 06, 10:19 AM, Michael Wenk <wenk at praxis.homedns.org> said:
> Pete,
> 
> I am not sure if this is the full story or not(or whether its standard or not, 
> this is just my opinion. YMMV)  Its pretty rare in my experience to pass by 
> value chars(either unsigned or signed), I mean look at functions like memset 
> and strchr, they take ints for what usually is a char. So when you pass 
> strings around(which are pointers to character), it probably concerns itself 
> more with the signedness.  I am curious how you compiled?  Did you 
> have -Wall ?  If not, does that change things?  
> 
> mike    
> 
> On Friday 02 June 2006 08:31 am, Peter Jay Salzman wrote:
> > I've been learning Java's JNI API, and came across something about C that I
> > never knew.
> >
> > There are 3 types of char:
> >
> >    char
> >    signed char
> >    unsigned char
> >
> > My understanding of the standard says that char can either be of type
> > "signed char" or "unsigned char"; it's implementation specific.  By
> > assigning "c = 255" I found that on my own platform (GNU/x86) a char is
> > implemented as a "signed char".  I think I remember reading that on Apple
> > platforms, it's implemented as an "unsigned char".
> >
> > According to the gcc info page:
> >
> >      Ideally, a portable program should always use `signed char' or
> >      `unsigned char' when it depends on the signedness of an object.
> >      But many programs have been written to use plain `char' and expect
> >      it to be signed, or expect it to be unsigned, depending on the
> >      machines they were written for.  This option, and its inverse, let
> >      you make such a program work with the opposite default.
> >
> > *    The type `char' is always a distinct type from each of `signed
> > *    char' or `unsigned char', even though its behavior is always just
> > *    like one of those two.
> >
> > char is a *distinct type* from "signed char" or "unsigned char".  That
> > surprised me.  So I did some experimentation and here's what I found.
> >
> > Apparently, there's no problem assigning the different chars to each other.
> > The compiler does the automatic conversion:
> >
> >    char          a = 0;
> >    signed char   b = 0;
> >    unsigned char c = 0;
> >
> >    a = b; a = c;    // fine.
> >    b = a; b = c;    // fine.
> >    c = a; c = b;    // fine.
> >
> > You can even pass the different types of char to functions that take
> > other types of char:
> >
> >    void takesAChar( char x, signed char y, unsigned char z );
> >
> >    takesAChar(a, b, c); takesAChar(a, c, b);  // fine.
> >    takesAChar(b, a, c); takesAChar(b, c, a);  // fine.
> >    takesAChar(c, b, a); takesAChar(c, a, b);  // fine.
> >
> > What the compiler complains about is passing *pointers* to different
> > types of char:
> >
> >    void takesACharPtr( char *x, signed char *y, unsigned char *z );
> >
> >    takesACharPtr(&a, &b, &c); takesACharPtr(&a, &c, &b);  // warnings.
> >    takesACharPtr(&b, &a, &c); takesACharPtr(&b, &c, &a);  // warnings.
> >    takesACharPtr(&c, &a, &b); takesACharPtr(&c, &b, &a);  // warnings.
> >
> > The warning is:
> >
> >    pointer targets in passing argument foo of bar differ in signedness.
> >
> > I'm trying to understand this.  I'm fairly sure the standard says that all
> > 3 types of char must have the same width.  For pointer operations like:
> >
> >    char s[] = "hello";
> >    unsigned char *cptr = s;
> >    ++cptr;
> >    putc( *cptr, stdout );
> >
> > will correctly print "e" because "char" and "unsigned char" have the same
> > width, and when we add one to cptr, it points to the correct location in
> > memory.
> >
> > What I'm getting at is this.  Because all the chars have the same width, it
> > doesn't matter WHAT kind of pointer you pass in to a function: char, signed
> > char, or unsigned char.  Pointer arithmetic just works, and it works
> > because they all have the same width.
> >
> > On the other hand, the data is what gets mangled if you don't use the
> > correct type:
> >
> >    char c = 255;
> >    printf("%d", c);
> >
> > prints, as expected, -1.  Not 255.
> >
> > So it seems to me that if the compiler complains about anything, it should
> > complain about passing a different type of char, not a different type of
> > char *.
> >
> > Why does gcc 4 complain about passing different "char *" and not "char"?
> >
> > And is this because of the standard or is it gcc specific?
> >
> > Thanks!
> > Pete
> > _______________________________________________
> > vox-tech mailing list
> > vox-tech at lists.lugod.org
> > http://lists.lugod.org/mailman/listinfo/vox-tech
> _______________________________________________
> vox-tech mailing list
> vox-tech at lists.lugod.org
> http://lists.lugod.org/mailman/listinfo/vox-tech

-- 
Peter Jay Salzman, Ph.D.
http://www.dirac.org/p p at dirac.org
pgp: B9F1 6CF3 47C4 7CD8 D33E  70A9 A3B9 1945 67EA 951D

"Coffee... I've conquered the Borg on coffee!"
       -- Kathryn Janeway on the virtues of coffee


More information about the vox-tech mailing list