By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,906 Members | 1,771 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,906 IT Pros & Developers. It's quick & easy.

sizeof stuff and declarations

P: n/a
I have two questions. I hope they are about C. I chose to post
here instead of comp.unix.programmer (or some other) because I do
think this is a C question.

Question 1:

%cat float.c
main() {
float **m = malloc(5 * sizeof(float*));
m[0] = malloc( sizeof(float) );
m[0][0] = 1.2;
printf("%f\n",m[0][0]);
}

Is this legal? I never really declare and assign so fast, but I
was wondering if it works because I'm lucky or if it really is
legal. Gcc doesn't like it much.

%gcc -c float.c
float.c: In function `main':
float.c:2: warning: initialization makes pointer from integer
without a cast float.c:3: warning: assignment makes pointer from
integer without a cast

Question 2:

(gdb) p sizeof(int)
$1 = 4
(gdb) p sizeof(long)
$2 = 4

I was expecting to see long a little bigger.
Why are they the same size?

Thank you.
Nov 14 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Kevin wrote:
I have two questions. I hope they are about C. I chose to post
here instead of comp.unix.programmer (or some other) because I do
think this is a C question.

Question 1:

%cat float.c
main() {
float **m = malloc(5 * sizeof(float*));
m[0] = malloc( sizeof(float) );
m[0][0] = 1.2;
printf("%f\n",m[0][0]);
}

Is this legal? I never really declare and assign so fast, but I
was wondering if it works because I'm lucky or if it really is
legal. Gcc doesn't like it much.

%gcc -c float.c
float.c: In function `main':
float.c:2: warning: initialization makes pointer from integer
without a cast float.c:3: warning: assignment makes pointer from
integer without a cast
You forgot do declare 'malloc' functions. That's what causes the
warning, since the compiler assumes that 'malloc' returns an 'int'.
Place '#include <stdlib.h>' at the beginning of your source file and the
warning will go away.

You also forgot to declare 'printf' function. 'printf' is a variadic
function. It mast be declared before use, or the behavior is undefined.
Add '#include <stdio.h>' at the beginning of your source file.

Otherwise, the code is legal.
Question 2:

(gdb) p sizeof(int)
$1 = 4
(gdb) p sizeof(long)
$2 = 4

I was expecting to see long a little bigger.
Why are they the same size?


Why not? This is perfectly legal in C. 'long' is not required to be
bigger than 'int'.

--
Best regards,
Andrey Tarasevich
Nov 14 '05 #2

P: n/a
On Thu, 17 Mar 2005 15:03:23 -0800,
Andrey Tarasevich <an**************@hotmail.com> wrote:
Kevin wrote:

[...]
Question 2:

(gdb) p sizeof(int)
$1 = 4
(gdb) p sizeof(long)
$2 = 4

I was expecting to see long a little bigger.
Why are they the same size?


Why not? This is perfectly legal in C. 'long' is not required
to be bigger than 'int'.


But if they take the same amount of bytes, then how is it
possible that long can take bigger numbers?

Thanks, Andrey.
Nov 14 '05 #3

P: n/a
Kevin wrote:
...
> Question 2:
>
> (gdb) p sizeof(int)
> $1 = 4
> (gdb) p sizeof(long)
> $2 = 4
>
> I was expecting to see long a little bigger.
> Why are they the same size?


Why not? This is perfectly legal in C. 'long' is not required
to be bigger than 'int'.


But if they take the same amount of bytes, then how is it
possible that long can take bigger numbers?
...


Well, the _guaranteed_ range of type 'long' is indeed wider than that of
type 'int' (per C99 standard). But in actual implementation it is not
required to be strictly wider. Internally 'int' and 'long' can be
implemented in exactly the same way, which is the case on your platform,
I'm sure.

A more pedantic answer (which you probably don't care about, so you can
stop reading now :) is that by applying 'sizeof' to a type you get the
number of bytes in the so called 'object representation' of that type.
If you multiply that value by CHAR_BIT, you'll get the number of bits in
the object representation of the type. But not all of those bits are
actually required to participate in the value representation. Some of
those object representation bits can remain "unused" (they are called
"padding" bits). For example, let's assume that on your platform
CHAR_BIT is 8. In this case on your platform the object representation
of both 'int' and 'long' contains 32 bits. But theoretically it is
possible that 'int' uses only 16 of those bits (and other 16 are just
padding) and 'long' uses all 32. In this case 'long' would be able to
take bigger numbers than 'int' and at the same time 'sizeof' of those
types would still be the same.

--
Best regards,
Andrey Tarasevich
Nov 14 '05 #4

P: n/a
> Kevin wrote:
%cat float.c
main() {
float **m = malloc(5 * sizeof(float*));
m[0] = malloc( sizeof(float) );
m[0][0] = 1.2;
printf("%f\n",m[0][0]);
}

Is this legal? I never really declare and assign so fast,
but I was wondering if it works because I'm lucky or if it
really is legal. Gcc doesn't like it much.

%gcc -c float.c
float.c: In function `main':
float.c:2: warning: initialization makes pointer from
integer without a cast float.c:3: warning: assignment
makes pointer from integer without a cast

Andrey Tarasevich wrote: You forgot do declare 'malloc' functions. That's what causes
the warning, since the compiler assumes that 'malloc' returns
an 'int'. Place '#include <stdlib.h>' at the beginning of your
source file and the warning will go away.

You also forgot to declare 'printf' function. 'printf' is a
variadic function. It mast be declared before use, or the
behavior is undefined.
Add '#include <stdio.h>' at the beginning of your source file.

Otherwise, the code is legal.


Depends what you mean by 'legal'? ;)

The implicit int declaration requires a diagnostic in C99. The
lack of return value from main means the status returned to the
host is undefined in C90. There is also the small matter of not
checking the return value from malloc.

--
Peter

Nov 14 '05 #5

P: n/a
On Thu, 17 Mar 2005 15:28:46 -0800,
Andrey Tarasevich <an**************@hotmail.com> wrote:
Kevin wrote:
...
> Question 2:
>
> (gdb) p sizeof(int)
> $1 = 4
> (gdb) p sizeof(long)
> $2 = 4
>
> I was expecting to see long a little bigger.
> Why are they the same size?

Why not? This is perfectly legal in C. 'long' is notrequired> to be bigger than 'int'.

But if they take the same amount of bytes, then how is it
possible that long can take bigger numbers?
...


Well, the _guaranteed_ range of type 'long' is indeed wider
than that of type 'int' (per C99 standard). But in actual
implementation it is not required to be strictly wider.
Internally 'int' and 'long' can be implemented in exactly the
same way, which is the case on your platform, I'm sure.


Yes, you're right about my platform.
A more pedantic answer (which you probably don't care about, so
you can stop reading now :) is that by applying 'sizeof' to a
That's the answer I was looking for :-) Thank you.
type you get the number of bytes in the so called 'object
representation' of that type. If you multiply that value by
CHAR_BIT, you'll get the number of bits in the object
representation of the type. But not all of those bits are
actually required to participate in the value representation.
Some of those object representation bits can remain "unused"
(they are called"padding" bits). For example, let's assume that
on your platform CHAR_BIT is 8. In this case on your platform
the object representation of both 'int' and 'long' contains 32
bits. But theoretically it is possible that 'int' uses only 16
of those bits (and other 16 are just padding) and 'long' uses
all 32. In this case 'long' would be able to take bigger
numbers than 'int' and at the same time 'sizeof' of those types
would still be the same.


I see. That's what happens here then. I get 4 bytes in int, but I
can't use them all. That explains. The reason why an int takes 4
bytes is probably for compilers/whatever have an easy time
dealing with it. Is that right?

So anyway, if on my platform they both take the same amount of
bytes, I would conclude that I should never use an int (unless to
conform with a function prototype or something) because I will
consume the same amount of bytes when using a long. And by using
a long, at least I will have the freedom to use all the bits I
allocated.

Am I right, here? Or did I misunderstand everything? Thank you.
Nov 14 '05 #6

P: n/a
Kevin wrote:
...
A more pedantic answer (which you probably don't care about, so
you can stop reading now :) is that by applying 'sizeof' to a


That's the answer I was looking for :-) Thank you.
type you get the number of bytes in the so called 'object
representation' of that type. If you multiply that value by
CHAR_BIT, you'll get the number of bits in the object
representation of the type. But not all of those bits are
actually required to participate in the value representation.
Some of those object representation bits can remain "unused"
(they are called"padding" bits). For example, let's assume that
on your platform CHAR_BIT is 8. In this case on your platform
the object representation of both 'int' and 'long' contains 32
bits. But theoretically it is possible that 'int' uses only 16
of those bits (and other 16 are just padding) and 'long' uses
all 32. In this case 'long' would be able to take bigger
numbers than 'int' and at the same time 'sizeof' of those types
would still be the same.


I see. That's what happens here then. I get 4 bytes in int, but I
can't use them all. That explains. The reason why an int takes 4
bytes is probably for compilers/whatever have an easy time
dealing with it. Is that right?

So anyway, if on my platform they both take the same amount of
bytes, I would conclude that I should never use an int (unless to
conform with a function prototype or something) because I will
consume the same amount of bytes when using a long. And by using
a long, at least I will have the freedom to use all the bits I
allocated.

Am I right, here? Or did I misunderstand everything? Thank you.


I don't think this is the case. You must've misunderstood me. The reason
I called the above answer "pedantic" (and the reason I assumed that you
don't care about it) is that normally in practice objects of integral
types don't contain any padding bits (unless you are working on some
very exotic platform).

In your case, I'm [almost] sure, all bits of an 'int' object are used in
the value representation of that type. The C standard requires that
objects of type 'int' can hold _at_ _least_ values in -32767 - +32767
range. Note: _at_ _least_. Which means that if on some platform objects
of type 'int' can hold values in -2147483647 - +2147483647 range (which
also happens to be the guaranteed range of 'long' type), the
requirements of the standard are still formally satisfied. You simply
got a "free extension" of the range of your 'int' type. You can use this
"free extension" as you see fit. Bot keep in mind that if you want your
code to be absolutely portable, you shouldn't rely on the 'int's range
being that wide. On some other platform it could happen to be only
-32767 - +32767.

Once again, the specification of the C language doesn't require type
'int' to be neither narrower (in terms of value range) nor smaller (in
therms of 'sizeof') than type 'long'.

--
Best regards,
Andrey Tarasevich
Nov 14 '05 #7

P: n/a
On Thu, 17 Mar 2005 16:32:46 -0800,
Andrey Tarasevich <an**************@hotmail.com> wrote:
Kevin wrote:
...
A more pedantic answer (which you probably don't care about,so> you can stop reading now :) is that by applying 'sizeof'
to a

That's the answer I was looking for :-) Thank you.
type you get the number of bytes in the so called 'object
representation' of that type. If you multiply that value by
CHAR_BIT, you'll get the number of bits in the object
representation of the type. But not all of those bits are
actually required to participate in the value

representation.> Some of those object representation bits can
remain "unused"> (they are called"padding" bits). For example,
let's assume that> on your platform CHAR_BIT is 8. In this
case on your platform> the object representation of both 'int'
and 'long' contains 32> bits. But theoretically it is possible
that 'int' uses only 16> of those bits (and other 16 are just
padding) and 'long' uses> all 32. In this case 'long' would be
able to take bigger> numbers than 'int' and at the same time
'sizeof' of those types> would still be the same.

I see. That's what happens here then. I get 4 bytes in int,
but I can't use them all. That explains. The reason why an
int takes 4 bytes is probably for compilers/whatever have an
easy time dealing with it. Is that right?

So anyway, if on my platform they both take the same amount
of bytes, I would conclude that I should never use an int
(unless to conform with a function prototype or something)
because I will consume the same amount of bytes when using a
long. And by using a long, at least I will have the freedom
to use all the bits I allocated.

Am I right, here? Or did I misunderstand everything? Thank
you.


I don't think this is the case. You must've misunderstood me.
The reason I called the above answer "pedantic" (and the reason
I assumed that you don't care about it) is that normally in
practice objects of integral types don't contain any padding
bits (unless you are working on some very exotic platform).


Okay, sorry then. Let's see if I understood you now.

In your case, I'm [almost] sure, all bits of an 'int' object
are used in the value representation of that type. The C
standard requires that objects of type 'int' can hold _at_
_least_ values in -32767 - +32767 range. Note: _at_ _least_.
Which means that if on some platform objects of type 'int' can
hold values in -2147483647 - +2147483647 range (which also
happens to be the guaranteed range of 'long' type), the
requirements of the standard are still formally satisfied. You
simply got a "free extension" of the range of your 'int' type.
You can use this"free extension" as you see fit. Bot keep in
mind that if you want your code to be absolutely portable, you
shouldn't rely on the 'int's range being that wide. On some
other platform it could happen to be only-32767 - +32767.


So, in my case (freebsd/intel) I have the benefit of having int
just as big as a long? But as I think you explained, I should not
rely on this, because my code may not be portable then.

Did I get it now?

I wrote:
(gdb) list 0
1 main() {
2
3 unsigned int i;
4 unsigned long j;
5
6 i = 4294967295U;
7 j = 4294967295U;
8
9
10 }
(gdb) p i
$4 = 4294967295
(gdb) p j
$5 = 4294967295

Thank you.
Nov 14 '05 #8

P: n/a
[on machine X, "sizeof(int)" and "sizeof(long)" are the same]
On Thu, 17 Mar 2005 15:03:23 -0800,
Andrey Tarasevich <an**************@hotmail.com> wrote:
Why not? This is perfectly legal in C. 'long' is not required
to be bigger than 'int'.

In article <20***************************@hotmail.com>
Kevin <ke***@hotmail.com> wrote:But if they take the same amount of bytes, then how is it
possible that long can take bigger numbers?


Maybe it can't -- on machine X anyway.

An analogy might help. Suppose the motor-vehicle administration
(DMV or MVA or whatever it is called where you are) says that you
need a different kind of license to drive a motorcycle vs a car vs
a tractor-trailer. You only have a "regular car" license. Suppose
also that they say "a car must hold two or more people side by
side". If your vehicle holds eight people, two in front seats and
three in second and third row seats, is it a car? (What if it
holds two or so people but can pull a triple trailer? :-) )

The C standard says that an "int" variable must hold, at the least,
values in the range -32767 to +32767, and "long" has to cover at
least -2147483647 to +2147483647. If your "int" and "long" both
happen to hold values in the range -2147483648 to +2147483647, is
that sufficient?

It is not unusual for a standard (or a law) to set some sort of
"least quality required" limit, and for people to exceed that, for
whatever reason.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #9

P: n/a
Kevin wrote:
...
In your case, I'm [almost] sure, all bits of an 'int' object
are used in the value representation of that type. The C
standard requires that objects of type 'int' can hold _at_
_least_ values in -32767 - +32767 range. Note: _at_ _least_.
Which means that if on some platform objects of type 'int' can
hold values in -2147483647 - +2147483647 range (which also
happens to be the guaranteed range of 'long' type), the
requirements of the standard are still formally satisfied. You
simply got a "free extension" of the range of your 'int' type.
You can use this"free extension" as you see fit. Bot keep in
mind that if you want your code to be absolutely portable, you
shouldn't rely on the 'int's range being that wide. On some
other platform it could happen to be only-32767 - +32767.
So, in my case (freebsd/intel) I have the benefit of having int
just as big as a long?


Exactly!
But as I think you explained, I should not
rely on this, because my code may not be portable then.

Did I get it now?


Yes. Whether you should rely on this or not is up to you. You shouldn't
rely on this if you want you code to be absolutely-pedantically-formally
portable. In practice this level of formal portability is rarely
required. I, for example, work with several platforms, all of which use
plain 'int's with 32-bit value range. I have no problem relying on this
fact in my code, because I'm pretty sure that I'll never encounter a
16-bit-'int' platform in my field.

--
Best regards,
Andrey Tarasevich
Nov 14 '05 #10

P: n/a
On 18 Mar 2005 01:24:10 GMT,
Chris Torek <no****@torek.net> wrote:
[on machine X, "sizeof(int)" and "sizeof(long)" are the same]
On Thu, 17 Mar 2005 15:03:23 -0800,
Andrey Tarasevich <an**************@hotmail.com> wrote:
Why not? This is perfectly legal in C. 'long' is notrequired> to be bigger than 'int'.


In article <20***************************@hotmail.com>
Kevin <ke***@hotmail.com> wrote:
But if they take the same amount of bytes, then how is it
possible that long can take bigger numbers?


Maybe it can't -- on machine X anyway.


Right.

An analogy might help. Suppose the motor-vehicle
administration(DMV or MVA or whatever it is called where you
are) says that you need a different kind of license to drive a
motorcycle vs a car vs a tractor-trailer. You only have a
"regular car" license. Suppose also that they say "a car must
hold two or more people side by side". If your vehicle holds
eight people, two in front seats and three in second and third
row seats, is it a car? (What if it holds two or so people but
can pull a triple trailer? :-) )
To be honest, I'm not sure how to answer, but here's my attempt:

Question 1: Is it a car? Yes. Because to be a car, must hold
two or more people side by side. My vehicle holds eight people
such that:

(a) two in front seats (respects the rule)
(b) three in second row (respect the rule: ``or more'')
(c) three in third row (respect the rule: ``or more'')

Therefore it's a car. I assume that the seats in each row are
really ``side by side''.

Question 2: What if it can pull a triple trailer?

I don't know what a triple trailer is... but as long as your car
respects the rule above, then it's a car. If a car couldn't pull
something, then it should be specified what it can't do. Is isn't
specified, so we are not breaking the rule.

I hope I got it :-)

The C standard says that an "int" variable must hold, at the
least, values in the range -32767 to +32767, and "long" has to
cover at least -2147483647 to +2147483647. If your "int" and
"long" both happen to hold values in the range -2147483648 to
+2147483647, is that sufficient?
Yes, it's sufficient. More than sufficient actually. It's
necessary for an int to allow -32767 to +32767, if you allow
more, than it's all good. Right?

It is not unusual for a standard (or a law) to set some sort of
"least quality required" limit, and for people to exceed that,
for whatever reason.


Yeah, I think I understand it now... I hope I do :-)

Thank you.
Nov 14 '05 #11

P: n/a
On modern systems, it's very common either for short and int to be the
same size, or for int and long to be the same size.

Roughly speaking:
char has to be at least 8 bits
short has to be at least 16 bits (and at least as wide as char)
int has to be at least 16 bits (and at least as wide as short)
long has to be at least 32 bits (and at least as wide as int)

There's often an advantage in having predefined integer types of sizes
8, 16, and 32 bits. Without defining additional types, there are
several ways to do this (assuming all sizes are powers of 2):
char 8 bits
short 16 bits
int 16 bits
long 32 bits
or
char 8 bits
short 16 bits
int 32 bits
long 32 bits
or
char 8 bits
short 16 bits
int 32 bits
long 64 bits

You're likely to see the latter only on 64-bit systems.

Even on 64-bit systems, int is likely to be only 32 bits, because
making it 64 bits leaves a hole in the type system (either there's no
16-bit type, or there's no 32-bit type); Cray systems, however, have
64-bit ints anyway.

None of this is guaranteed, and there's seldom any great need to
assume that it is. You can write code that doesn't make any
assumptions beyond what's guaranteed by the standard.

C99 introduces typedefs for exact-width types: int16_t, int32_t,
int64_t, and so forth.

(Above, I wrote "Roughly speaking" because what the standard
guarantees isn't these sizes. Instead, it guarantees certain
representable ranges; either -127..+127 or 0..255 for char,
-32767..+32767 for short and int, -2147483647..+2147483647 for long.
These usually translate to the specified number of bits, but extra
padding bits are permitted. With padding bits, it's even possible to
have sizeof(short) > sizeof(int), but I don't think any real
implementations do this. Also, for a 16-bit type, the range is more
likely to be -32728..+32767 rather than -32767..+32767; the standard's
minimum ranges allow for sign-magnitude and one's-complement
representations, but two's-complement is much more common these days.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #12

P: n/a
This is off-topic but what the heck... :-)
On 18 Mar 2005 01:24:10 GMT,
Chris Torek <no****@torek.net> wrote:
An analogy might help. ... motorcycle vs a car vs a tractor-trailer. ...
... is it a car? (What if it holds two or so people but
can pull a triple trailer? :-) )

In article <20***************************@hotmail.com>
Kevin <ke***@hotmail.com> wrote [in part]:I don't know what a triple trailer is... but as long as your car
respects the rule above, then it's a car.
If you are familiar with "18-wheelers" at all, you know what a
tractor cab is (e.g., a Peterbilt or a Mack). These tow trailers.
Trailers can be doubled-up or even tripled-up, so that one cab is
pulling three trailers. Some states put limits on the train-length;
I believe triples are outlawed in all of Caliornia, for instance.
If a car couldn't pull something, then it should be specified what
it can't do. Is isn't specified, so we are not breaking the rule.

I hope I got it :-)


Pretty much, yes. Sometimes the specifications are a bit lacking.
There is an enormous pickup truck (that does qualify as a "pickup
truck", despite being 21.5 feet long and 9 feet high) that I suspect
could pull trailers, and hence cross the somewhat fuzzy line between
"ordinary car" drivers' licenses and commercial truck drivers'
licenses. Of course, Hummers are already so heavy (over 6000 pounds
"gross vehicle weight") that they are illegal on most California
suburban streets -- but good luck finding anyone to enforce that
when Arnold Schwarzenegger is out for a drive. :-)

(The truck -- the International CXT -- has a GVWR of 25,999 lbs,
which is just under the line for requiring a Class B license.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.