integer promotions

J

jimjim

Hi all,

Assume x is declared as char x, and a function f( ) with prototype void
f(char y).

Assume f( ) is invoked somewhere in the code and:

1. The f( )'s prototype is provided, then an one-byte copy of x is passed to
f( ) (unix/intel platform).
2. The prototype is not provided, then a four-byte int, which contains the
value of x, is passed to f( ) (unix/intel platform).
3. If f( ) was a variadic function instead, a four-byte int, which contains
the value of x, is passed to f( ) unix/intel platform).

Right?

TIA
 
R

Roberto Waltman

jimjim said:
Assume x is declared as char x, and a function f( ) with prototype void
f(char y).
Assume f( ) is invoked somewhere in the code and:
1. The f( )'s prototype is provided, then an one-byte copy of x is passed to
f( ) (unix/intel platform).
2. The prototype is not provided, then a four-byte int, which contains the
value of x, is passed to f( ) (unix/intel platform).

Yes, but only if you are assuming that a char variable is stored in a
single byte (define byte?) and the sizeof(int) is 4.
Most likely true in a "unix/intel platform", but not necessarily so.
( I am currently working on code running on a TI 2812 DSP. There is
no byte (octet) addressing, both char and int types are 16 bits )
3. If f( ) was a variadic function instead, a four-byte int, which contains
the value of x, is passed to f( ) unix/intel platform).

Not applicable to this f(). A variadic function must have at least
one "regular" parameter.

Roberto Waltman

[ Please reply to the group, ]
[ return address is invalid. ]
 
D

Dik T. Winter

> 3. If f( ) was a variadic function instead, a four-byte int, which contains
> the value of x, is passed to f( ) unix/intel platform).

No, see my article in the other thread.
 
J

Jack Klein

Hi all,

Assume x is declared as char x, and a function f( ) with prototype void
f(char y).

Assume f( ) is invoked somewhere in the code and:

1. The f( )'s prototype is provided, then an one-byte copy of x is passed to
f( ) (unix/intel platform).

No, the value of 'x' is passed as a char, which is one byte by
definition in C (but may have more than 8-bits).
2. The prototype is not provided, then a four-byte int, which contains the
value of x, is passed to f( ) (unix/intel platform).

If you call a function without a prototype in scope, the number and
types of arguments that you call it with, after the default
promotions, must exactly match the number and types of arguments the
function is defined to accept. If this is not true, you produce
undefined behavior, so it doesn't matter here what happens because
it's game over, you lose.

So if you have a function that accepts a parameter of a float, plain,
signed, or unsigned char, or signed or unsigned short, you can't call
it without a prototype in scope. Well you can, but we don't talk
about it here, because neither we nor the C language know or care what
happens. It might wipe the UNIX OS off your box and install Windows
95, for all we care.
3. If f( ) was a variadic function instead, a four-byte int, which contains
the value of x, is passed to f( ) unix/intel platform).

If f() was a variadic function, there must be a prototype in scope
when you call it, or you're back to undefined behavior and we don't
care. If there is a variadic function, and the char is passed to one
of the arguments in the "..." portion, then the value of the char is
promoted to an int and the int is passed by value. That int is
sizeof(int) bytes, which is sometimes one byte but usually more.

But it is always sizeof(int) bytes, and that is true whatever the
platform is. If the platform is important to your question, you are
wrong to ask it here.

Well, no, not completely.

If you don't know what sizeof(int) is on your platform, compile and
run the following program:

#include <stdio.h>
int main(void)
{
printf("sizeof(int) is %d\n", (int)sizeof(int));
return 0;
}
 
J

jimjim

1. The f( )'s prototype is provided, then an one-byte copy of x is passed
No, the value of 'x' is passed as a char, which is one byte by
definition in C (but may have more than 8-bits).
As x on a unix/intel platform is 8-bits *, I would say that x 's value is
essentially an 8-bit integer number, which depending on the interpretation
may be displayed as a character or an integer value. So, I would say that
this integer number is passed to the f( ) function.
(1) Is this right?
(2) You said that x is passed as a char. Can you exlain what does this
mean, please?

* Given that currently character sets may have different width, should I
assume that C standard's definition of a char as one byte (which in the
context of computer science by definition is 8-bits) is a histrorical left
over?
If you call a function without a prototype in scope, the number and
types of arguments that you call it with, after the default
promotions, must exactly match the number and types of arguments the
function is defined to accept. If this is not true, you produce
undefined behavior, so it doesn't matter here what happens because
it's game over, you lose.
Ohh i see. So, because I havent provided a prototype in scope, char x is
promoted to an int. But because f( ) actually accepts a char, undefined
behavior is invoked. thx
So if you have a function that accepts a parameter of a float, plain,
signed, or unsigned char, or signed or unsigned short, you can't call
it without a prototype in scope.
I see. thx
If f() was a variadic function, there must be a prototype in scope
when you call it, or you're back to undefined behavior and we don't
care.
Is this because the compiler explicitly needs to know the types of arguments
before the "..."?
If there is a variadic function, and the char is passed to one
of the arguments in the "..." portion, then the value of the char is
promoted to an int and the int is passed by value. That int is
sizeof(int) bytes, which is sometimes one byte but usually more.
Ohh, thats why we use va_arg(ap, int) for an argument of type char.

Thx
 
I

Irrwahn Grausewitz

jimjim said:
* Given that currently character sets may have different width, should I
assume that C standard's definition of a char as one byte (which in the
context of computer science by definition is 8-bits)

No. A char is of size one byte by definition, and I don't expect this
to be changed in any forthcoming C standard. Note, that the somewhat
common definition of a byte consisting of an octet of bits has no
bearing on the definition of byte in the C standard:

C99 3.6
byte
addressable unit of data storage large enough to hold any member of
the basic character set of the execution environment

C99 3.7.1
character
[...] bit representation that fits in a byte


5.2.4.2.1p1
The values given below shall be replaced by constant expressions
[...]. Their implementation-defined values shall be equal or greater
in magnitude (absolute value) to those shown, with the same sign.

- number of bits for smallest object that is not a bit-field (byte)
CHAR_BIT 8
[...]

In C a byte has to be /at least/ 8 bits wide, but that's about it.

I wouldn't be surprised, if this message had passed through several
systems with byte sizes > 8 bit until it reached its destination.
is a histrorical left over?

IIRC, among the first computers C was ever implemented on were
machines with a word size of 18 or 36 bits, so I'd say no. But I
leave it to the experts to give a definite answer.

Best regards
 
A

Anand

jimjim wrote:
[...]
* Given that currently character sets may have different width, should I
assume that C standard's definition of a char as one byte (which in the
context of computer science by definition is 8-bits) is a histrorical left
over?
[...]
Few corrections (the ones I got clarified few days ago)

Byte is *not* 8 bits .. yes now most of the systems (all of those I know
of have 8 bits.. so it's become a defacto)

C's definition of byte need not be same as underlying systems definition
of byte.

Here are few guarantees of C:
1) char is 1 byte ( hence sizeof(char) is *always* 1)
2) for ex: signed char the range of -127(SCHAR_MIN) to (SCHAR_MAX) +127
(or a bigger range than this)
3) CHAR_BIT of \at least\ 8 bits


So on a system where system's byte size is greater or equals to 8 bits
it's straight fwd as all 3 conditions will be automatically satisfied
(CHAR_BIT, SCHAR_MIN, SCHAR_MAX etc.. will be different than what you
see if a 8-bit byte system)

On the systems where system's byte is lesser than 8 bits then C's byte
definition would represent more than one system-byte.
For ex. if the system-byte size is 7 bits then CHAR_BIT would be 14
(7*2) etc.
 
A

Anand

jimjim wrote:
[...]
* Given that currently character sets may have different width, should I
assume that C standard's definition of a char as one byte (which in the
context of computer science by definition is 8-bits) is a histrorical left
over?
[...]
Few corrections (the ones I got clarified few days ago)

Byte is *not* 8 bits .. yes now most of the systems (all of those I know
of have 8 bits.. so it's become a defacto)

C's definition of byte need not be same as underlying systems definition
of byte.

Here are few guarantees of C:
1) char is *always* 1 byte ( hence sizeof(char) is *always* 1)
2) for ex: signed char the range of -127(SCHAR_MIN) to (SCHAR_MAX) +127
(or a bigger range than this)
3) CHAR_BIT of \at least\ 8 bits


So on a system where system's byte size is greater or equals to 8 bits
it's straight fwd as all 3 conditions will be automatically satisfied
(CHAR_BIT, SCHAR_MIN, SCHAR_MAX etc.. will be different than what you
see if a 8-bit byte system)

On the systems where system's byte is lesser than 8 bits then C's byte
definition would represent more than one system-byte.
For ex. if the system-byte size is 7 bits then CHAR_BIT would be 14
(7*2) etc.
 
J

jimjim

Here are few guarantees of C:
1) char is *always* 1 byte ( hence sizeof(char) is *always* 1)

Hmm, suppose I would like to allocate 2 chars with malloc: malloc( 2 *
sizeof (char)).
If sizeof(char) is *always* 1, on a platform that a char occupies 2 bytes I
have allocated 2 * 1 = 2 bytes, rather than 2 * 2bytes = 4 bytes.

This is a side question regarding malloc( ), which recieves one argument of
type size_t.
sizeof ( ) returns size_t. What happens when I multiply a number with
size_t, as malloc( 2 * sizeof (char))? Is this the right way to invoke
malloc( )?

TIA
 
A

Anand

jimjim said:
Hmm, suppose I would like to allocate 2 chars with malloc: malloc( 2 *
sizeof (char)).
If sizeof(char) is *always* 1, on a platform that a char occupies 2 bytes I

To reiterate:
Definition of byte may be different from C to it's underlying system.

char always occupy 1 C-byte, but internally it may be n-system bytes.

sizeof(char) in malloc is not required as it's guaranteed to be 1 by C.
(FAQ covers this)

So malloc(2) [or malloc(2* sizeof(char)), if you prefer] would always
allocate 2 C-bytes. Again... internally it may be 2n system-bytes, but
in C realm its immaterial.
have allocated 2 * 1 = 2 bytes, rather than 2 * 2bytes = 4 bytes.
The bytes you are talking about C-byte.
This is a side question regarding malloc( ), which recieves one argument of
type size_t.
sizeof ( ) returns size_t. What happens when I multiply a number with
size_t, as malloc( 2 * sizeof (char))? Is this the right way to invoke
malloc( )?

Here's what C99 has to say about sizeof and size_t
6.5.3.4: sizeof operator
....
4. The value of the result is implementation-defined, and its type
(an unsigned integer type) is size_t, defined in <stddef.h> (and other
headers).

you can conclude about the type by the above info (and boundary
conditions ... if you were worried about them)
 
A

Alexei A. Frounze

jimjim said:
Hmm, suppose I would like to allocate 2 chars with malloc: malloc( 2 *
sizeof (char)).

You don't need to multiply by sizeof(char), just malloc (2), that's it.
sizeof(char) is guaranteed to be precisely 1.
If sizeof(char) is *always* 1,

Yes, it always is 1.
on a platform that a char occupies 2 bytes

In C, the type char and the byte are different names for the same thing.
Your misunderstanding starts at the point where you define in your mind that
a byte is a memory cell containing precisely 8-bits. In fact, a byte(char)
is a minimum addressable unit of memory in the system and on different
systems it may indeed be different, e.g. 8 bits, 16 bits, anything. The C
standard simply requires that it's not smaller than 8 bits, but it's not
just the other way of saying that every byte/char is 8 bits long. It may be
bigger. Just forget of bytes/chars being always exactly 8 bits long and
you'll be OK.

Alex
P.S. remember that the type char usually isn't enough to hold a character
(see the Unicode standard).
 
I

Irrwahn Grausewitz

jimjim said:
Hmm, suppose I would like to allocate 2 chars with malloc: malloc( 2 *
sizeof (char)).
If sizeof(char) is *always* 1, on a platform that a char occupies 2 bytes I
have allocated 2 * 1 = 2 bytes, rather than 2 * 2bytes = 4 bytes.

You still mix up the different meanings of byte. In C an object
of type char *always* occupies 1 byte. If the size of this byte
coincides with the size of the smallest addressable unit the
underlying hardware provides, is of no concern, except for the
implementer.
This is a side question regarding malloc( ), which recieves one argument of
type size_t.
sizeof ( ) returns size_t. What happens when I multiply a number with
size_t,

You get the product of both. After all, size_t is nothing more than
an unsigned integer type, capable of holding values up to *at least*
65535.
as malloc( 2 * sizeof (char))? Is this the right way to invoke
malloc( )?

It's not actually wrong, but the sizeof (char) is spurious, because
it's 1 by definition. Usually you don't have to use sizeof(<type>)
in a malloc call at all:

Given p (a pointer to any complete object type) and N (the desired
number of objects to reserve memory for), the canonical way to call
malloc is:

p = malloc( N * sizeof *p )

This way the argument of malloc automagically adapts, even if the type
of object p points to is changed in future revisions of the program.

Best regards.
 
J

jimjim

Irrwahn Grausewitz said:
You still mix up the different meanings of byte. In C an object
of type char *always* occupies 1 byte. If the size of this byte
coincides with the size of the smallest addressable unit the
underlying hardware provides, is of no concern, except for the
implementer.
Got it. Even though 1 C-byte may map to 2 system-level bytes on a particular
platform, sizeof( char) is given to return 1. So, its the C standard
implementer's job to make sure that if the int on that particular platform
is 4 system-level bytes, sizeof(int) will return 2, so from the developer's
standpoint everything's transparent.
 
J

Jack Klein

* Given that currently character sets may have different width, should I
assume that C standard's definition of a char as one byte (which in the
context of computer science by definition is 8-bits) is a histrorical left
over?

Can you provide an authoritative reference defining a byte as 8 bits?
I think not, because you are in fact incorrect.

In the context of any knowledgeable computer scientist, a binary word
containing exactly 8 bits is universally by definition known as an
'octet'.

It seems to be the English speakers who naively make the mistake that
a byte is universally 8 bits and 8 bits is universally a byte. Native
speakers of at least some other languages use the abbreviation 'Mo'
(mega-octet or millions of octets) where many English speakers
incorrectly use 'MB', for megabyte.
 
J

Jack Klein

Hmm, suppose I would like to allocate 2 chars with malloc: malloc( 2 *
sizeof (char)).
If sizeof(char) is *always* 1, on a platform that a char occupies 2 bytes I
have allocated 2 * 1 = 2 bytes, rather than 2 * 2bytes = 4 bytes.

A char can't occupy two bytes. Not on any platform, ever. By
definition, byte is equal to the size of a character, and is the
amount of storage required to hold a char. Each and every byte is
directly addressable, and there is no room between the addresses of
two chars.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top