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

Re: Promoting unsigned long int to long int

P: n/a
pereges <Br*****@gmail.comwrites:
[...]
#define ulong unsigned long int
#define uchar unsigned char
[...]

These types already have perfectly good names already. Why give them
new ones?

If you must rename them for some reason, use typedefs, not macros.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 30 '08 #1
Share this Question
Share on Google+
105 Replies


P: n/a
On Jun 30, 8:49 pm, Keith Thompson <ks...@mib.orgwrote:
These types already have perfectly good names already. Why give them
new ones?
No purpose really. Just that in some of my functions, there are too
many parameters already and the whole thing doesn't fit in single
line.
If you must rename them for some reason, use typedefs, not macros.
ok
Jun 30 '08 #2

P: n/a
pereges <Br*****@gmail.comwrites:
On Jun 30, 8:49 pm, Keith Thompson <ks...@mib.orgwrote:
These types already have perfectly good names already. Why give them
new ones?

No purpose really. Just that in some of my functions, there are too
many parameters already and the whole thing doesn't fit in single
line.
So write it on multiple lines.

Given:
#define ulong unsigned long int
#define uchar unsigned char
or, preferably:
typedef unsigned long int ulong;
typedef unsigned char uchar;

If I'm reading your code and see a reference to "ulong", I can't
understand what it means until I've confirmed that "ulong" means
"unsigned long int" (which I'd probably write as "unsigned long").
And I have to wonder whether you might some day change the definition
so "ulong" means something else.

If you drop the definition of "ulong" and just write "unsigned long"
directly, I don't have to wonder; your code will be clearer.

Now if you want a typedef whose name says something about how you're
using the type, rather than how it's define, that's a different
matter.

You use "ulong" for array indices; it would make more sense to use
size_t.

You use "uchar" for a parameter that can only have the value 0, 1, or
2. I'd use int. Using unsigned char might save some space, but it's
just as likely to cost you in code size, since the compiler has to
generate code to expand the 1-byte value into a word before it can
operate on it, and to shrink it back down to 1 byte before storing it.
You also make the reader wonder whether there's some fundamental
reason for this value to fit into a byte (there isn't). If you had an
array of these things, it would make sense to use a smaller type.
Since it's just a single parameter, using int is fine.
If you must rename them for some reason, use typedefs, not macros.

ok
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 30 '08 #3

P: n/a
pereges <Br*****@gmail.comwrote:
On Jun 30, 8:49 pm, Keith Thompson <ks...@mib.orgwrote:
These types already have perfectly good names already. Why give them
new ones?
No purpose really. Just that in some of my functions, there are too
many parameters already and the whole thing doesn't fit in single
line.
You don't have to put all arguments etc. on a single line, e.g.

void
quicksort( vector ** parent_vpa,
unsigned long left,
unsigned long right,
unsigned char axis )

will do nicely and may even increases readabilty (and there's
still space for adding a short comment;-)

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Jun 30 '08 #4

P: n/a
On Jun 30, 9:43 pm, Keith Thompson <ks...@mib.orgwrote:
So write it on multiple lines.

Given:
#define ulong unsigned long int
#define uchar unsigned char
or, preferably:
typedef unsigned long int ulong;
typedef unsigned char uchar;

If I'm reading your code and see a reference to "ulong", I can't
understand what it means until I've confirmed that "ulong" means
"unsigned long int" (which I'd probably write as "unsigned long").
And I have to wonder whether you might some day change the definition
so "ulong" means something else.

If you drop the definition of "ulong" and just write "unsigned long"
directly, I don't have to wonder; your code will be clearer.

Now if you want a typedef whose name says something about how you're
using the type, rather than how it's define, that's a different
matter.

You use "ulong" for array indices; it would make more sense to use
size_t.

You use "uchar" for a parameter that can only have the value 0, 1, or
2. I'd use int. Using unsigned char might save some space, but it's
just as likely to cost you in code size, since the compiler has to
generate code to expand the 1-byte value into a word before it can
operate on it, and to shrink it back down to 1 byte before storing it.
You also make the reader wonder whether there's some fundamental
reason for this value to fit into a byte (there isn't). If you had an
array of these things, it would make sense to use a smaller type.
Since it's just a single parameter, using int is fine.
If I had to store 80-90 of structures and each had a member say
'axis'. How much of a difference would using a unsigned char over int
would make (for that member) ? For my program, space as well as
performance are important.
Jun 30 '08 #5

P: n/a
On Jun 30, 9:44 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
You don't have to put all arguments etc. on a single line, e.g.

void
quicksort( vector ** parent_vpa,
unsigned long left,
unsigned long right,
unsigned char axis )

will do nicely and may even increases readabilty (and there's
still space for adding a short comment;-)
Just a style question (I'm cleaning up my code)

Which of the two in your opinion is better ?

void quicksort( vector ** parent_vpa,
unsigned long left,
unsigned long right,
unsigned char axis ) {

....
....
}

OR

void quicksort( vector ** parent_vpa,
unsigned long left,
unsigned long right,
unsigned char axis )
{

....
....
}
Jun 30 '08 #6

P: n/a
pereges <Br*****@gmail.comwrites:
[...]
If I had to store 80-90 of structures and each had a member say
'axis'. How much of a difference would using a unsigned char over int
would make (for that member) ? For my program, space as well as
performance are important.
It depends.

If "axis" is the last member of your structure, it's likely that the
compiler will insert padding after it if it's an unsigned char anyway,
so declaring it as int would make no difference.

In the worst case (well, the worst plausible case), the cost of using
int would be 90 * (sizeof(int) - 1), which is trivial on anything
other than a small embedded system. But using int could easily save
code space, depending on the underlying architecture. And if you're
concerned about speed, it's likely (though by no means guaranteed)
that operations on int will be faster than operations on unsigned
char.

I think you're engaging in premature micro-optimization.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 30 '08 #7

P: n/a
pereges wrote:
If I had to store 80-90 of structures and each had a member say
'axis'. How much of a difference would using a unsigned char over int
would make (for that member) ? For my program, space as well as
performance are important.
On my machine it would make
no difference in terms of usable memory saved
and it would slow down the arithmetic operations.

An array of char will save usable space over an array of int;
but if I only define several distinct char objects in a function,
my compiler will place them on int boundaries.
Meaning that in between the char objects,
there are three bytes of unusable memory
(sizof(int) equals 4 on my machine).

char arithmetic on my machine
is accomplished in int size objects or registers,
requiring additional masking operations.

--
pete
Jun 30 '08 #8

P: n/a
btw, i see a lot of people saying that size_t must be used over
unsigned long. The question is are there any fix guidelines as to when
i should and when i shouldn't use size_t. It seems to me that size_t
is most commonly used in three situations :

1. Size of array or any object.
2. Array indices.
3. Count of something.

Although I don't see why using unsigned long for any of the above
could be wrong. It may not be a necessity to use size_t

Jun 30 '08 #9

P: n/a
pereges <Br*****@gmail.comwrote:
On Jun 30, 9:44 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
You don't have to put all arguments etc. on a single line, e.g.

void
quicksort( vector ** parent_vpa,
unsigned long left,
unsigned long right,
unsigned char axis )

will do nicely and may even increases readabilty (and there's
still space for adding a short comment;-)
Just a style question (I'm cleaning up my code)
Which of the two in your opinion is better ?
void quicksort( vector ** parent_vpa,
unsigned long left,
unsigned long right,
unsigned char axis ) {
....
....
}
OR
void quicksort( vector ** parent_vpa,
unsigned long left,
unsigned long right,
unsigned char axis )
{
....
....
}
I usually go for the way that has more white-space, probably
because my eyes aren't as good anymore as they used to be,
so I usually put the opening brace on a new line (at least
when I am writing C, in Perl I do it the other way round;-).
So I personally don't mind much. Just pick something that
looks good to you and is logically consistent (or, if you
are working somewhere, use the in-house style) and use that
consistently.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Jun 30 '08 #10

P: n/a
pereges <Br*****@gmail.comwrites:
btw, i see a lot of people saying that size_t must be used over
unsigned long. The question is are there any fix guidelines as to when
i should and when i shouldn't use size_t. It seems to me that size_t
is most commonly used in three situations :

1. Size of array or any object.
2. Array indices.
3. Count of something.

Although I don't see why using unsigned long for any of the above
could be wrong. It may not be a necessity to use size_t
size_t can represent the size in bytes of any object (since it's the
type of the result of the sizeof operator and of the argument to
malloc(). It can therefore represent the size in elements of any
array object, making it suitable for array indices.

The third is a bit more iffy; it depends on what you're counting.

But there are no such guarantees for unsigned long. Consider a
hypothetical system where unsigned long is 32 bits and size_t is 64
bits. You might have objects whose size cannnot be represented as an
unsigned long value.

The question is, why would you want to use unsigned long rather than
size_t?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 30 '08 #11

P: n/a
pereges wrote:
btw, i see a lot of people saying that size_t must be used over
unsigned long. The question is are there any fix guidelines as to when
i should and when i shouldn't use size_t. It seems to me that size_t
is most commonly used in three situations :

1. Size of array or any object.
2. Array indices.
3. Count of something.

Although I don't see why using unsigned long for any of the above
could be wrong. It may not be a necessity to use size_t
size_t is for counting parts of an object.
That's cases 1 and 2 of your list.
In terms of efficiency, you can expect that size_t
will probably be the fastest type that is big enough
to do the job.

When I count nodes in linked list, I use long unsigned.
The number of nodes that malloc can generate,
isn't related to size_t.

--
pete
Jun 30 '08 #12

P: n/a
pereges wrote:
btw, i see a lot of people saying that size_t must be used over
unsigned long. The question is are there any fix guidelines as to when
i should and when i shouldn't use size_t. It seems to me that size_t
is most commonly used in three situations :

1. Size of array or any object.
This is the purpose of size_t.
2. Array indices.
IMHO, any unsigned type of suitable range will do. Sometimes signed
types are convenient too, for certain forms of loops, and rarely, to
index with a negative offset.
3. Count of something.
Again a suitable unsigned type, not necessarily size_t should be okay.
Although I don't see why using unsigned long for any of the above
could be wrong. It may not be a necessity to use size_t
You are correct. In C, size_t has the only purpose of being large enough
to hold the size in bytes of the largest possible single object. Also
the sizeof operator yields a size_t value for related reasons. It is
not necessarily a suitable type for counting things are holding
offsets, indexes and such.

Generally, a careful examination of the origin, purpose and types of use
a value may be subject to will give you a clue as to the most suitable
type of object to represent it.

Jun 30 '08 #13

P: n/a
On Jun 30, 11:19 pm, santosh <santosh....@gmail.comwrote:
1. Size of array or any object.

This is the purpose of size_t.
2. Array indices.

IMHO, any unsigned type of suitable range will do. Sometimes signed
types are convenient too, for certain forms of loops, and rarely, to
index with a negative offset.
3. Count of something.

Again a suitable unsigned type, not necessarily size_t should be okay.
Although I don't see why using unsigned long for any of the above
could be wrong. It may not be a necessity to use size_t

You are correct. In C, size_t has the only purpose of being large enough
to hold the size in bytes of the largest possible single object. Also
the sizeof operator yields a size_t value for related reasons. It is
not necessarily a suitable type for counting things are holding
offsets, indexes and such.

Generally, a careful examination of the origin, purpose and types of use
a value may be subject to will give you a clue as to the most suitable
type of object to represent it.
Thanks for the clarification. After reading this, I guess I will
continue using unsigned long for all the 3 situations.
Jun 30 '08 #14

P: n/a
On Jun 30, 11:13 pm, Keith Thompson <ks...@mib.orgwrote:
size_t can represent the size in bytes of any object (since it's the
type of the result of the sizeof operator and of the argument to
malloc(). It can therefore represent the size in elements of any
array object, making it suitable for array indices.

The third is a bit more iffy; it depends on what you're counting.

But there are no such guarantees for unsigned long. Consider a
hypothetical system where unsigned long is 32 bits and size_t is 64
bits. You might have objects whose size cannnot be represented as an
unsigned long value.

The question is, why would you want to use unsigned long rather than
size_t?
Suppose I have a structure:

struct mesh
{
unsigned long nvert; /* number of vertices */
unsigned long ntri; /* number of triangles */
vector *vert; /* pointer to array of vertices */
triangle *tri; /* pointer to array of triangles */
};

Now, according to what you are saying nvert and ntri should have data
type size_t instead. In my program its possible for nvert and ntri to
be in millions. I have been adviced that size_t in many cases causes
loss of data, hence I'm skecptical about its use. Also, I would want
to keep things consistent.
Jun 30 '08 #15

P: n/a
pereges <Br*****@gmail.comwrites:
On Jun 30, 11:19 pm, santosh <santosh....@gmail.comwrote:
1. Size of array or any object.
This is the purpose of size_t.
2. Array indices.
IMHO, any unsigned type of suitable range will do. Sometimes signed
types are convenient too, for certain forms of loops, and rarely, to
index with a negative offset.
3. Count of something.
Again a suitable unsigned type, not necessarily size_t should be okay.
Although I don't see why using unsigned long for any of the above
could be wrong. It may not be a necessity to use size_t
You are correct. In C, size_t has the only purpose of being large enough
to hold the size in bytes of the largest possible single object. Also
the sizeof operator yields a size_t value for related reasons. It is
not necessarily a suitable type for counting things are holding
offsets, indexes and such.

Generally, a careful examination of the origin, purpose and types of use
a value may be subject to will give you a clue as to the most suitable
type of object to represent it.

Thanks for the clarification. After reading this, I guess I will
continue using unsigned long for all the 3 situations.
Um, why? It will probably work, but for case 1 size_t is exactly the
right type, and for case 2 it's guaranteed to work, while unsigned
long isn't.

It sounds like you want to use unsigned long if at all possible, and
use size_t only if it's absolutely necessary. Why is that?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 30 '08 #16

P: n/a
On Jul 1, 1:24 am, Keith Thompson <ks...@mib.orgwrote:
Um, why? It will probably work, but for case 1 size_t is exactly the
right type, and for case 2 it's guaranteed to work, while unsigned
long isn't.

It sounds like you want to use unsigned long if at all possible, and
use size_t only if it's absolutely necessary. Why is that?
Mainly because my project has grown beyond 1000 lines and now its
becoming more and more difficult to keep track of things. That's why I
wanted to keep things a little consistent.
Jun 30 '08 #17

P: n/a
btw can i sort an array of pointers with qsort function ?? I tried the
following but failed miserably as it reutrned the same unsorted list :
int cmp_coord_x(const void *vpa, const void *vpb)
{
const vector *va = vpa;
const vector *vb = vpb;

return (va->coord[0] < va->coord[0] ? -1 : vb->coord[0] vb-
>coord[0]);
}

int cmp_coord_y(const void *vpa, const void *vpb)
{
const vector *va = vpa;
const vector *vb = vpb;

return (va->coord[1] < va->coord[1] ? -1 : vb->coord[1] vb-
>coord[1]);
}

int cmp_coord_z(const void *vpa, const void *vpb)
{
const vector *va = vpa;
const vector *vb = vpb;

return (va->coord[2] < va->coord[2] ? -1 : vb->coord[2] vb-
>coord[2]);
}

/* axis is used as criterion on how we sort the array */
if (axis == 0)
{
qsort(parent_vpa, sizeof parent_vpa/ sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord_x);
}
if (axis == 1)
{
qsort(parent_vpa, sizeof parent_vpa/ sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord_y);
}
if (axis == 2)
{
qsort(parent_vpa, sizeof parent_vpa/ sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord_z);
}
Jun 30 '08 #18

P: n/a
pereges <Br*****@gmail.comwrites:
btw can i sort an array of pointers with qsort function ??
Yes, you can.
I tried the
following but failed miserably as it reutrned the same unsorted list :
int cmp_coord_x(const void *vpa, const void *vpb)
{
const vector *va = vpa;
const vector *vb = vpb;
The array is an array of vector *. The void * you get in the compare
points to an array element -- it is a void * but it points to a vector
**. This is in the FAQ. If you don't mind a cast:

const vector *va = *(const vector *const *)vpa;
const vector *vb = *(const vector *const *)vpb;
return (va->coord[0] < va->coord[0] ? -1 : vb->coord[0] vb->coord[0]);
You have your va's and vb's mixed up. I think you wanted:

return (va->coord[0] < vb->coord[0] ? -1 : va->coord[0] vb->coord[0]);
}

int cmp_coord_y(const void *vpa, const void *vpb)
{
const vector *va = vpa;
const vector *vb = vpb;

return (va->coord[1] < va->coord[1] ? -1 : vb->coord[1] vb-
>>coord[1]);
}

int cmp_coord_z(const void *vpa, const void *vpb)
{
const vector *va = vpa;
const vector *vb = vpb;

return (va->coord[2] < va->coord[2] ? -1 : vb->coord[2] vb-
>>coord[2]);
}

/* axis is used as criterion on how we sort the array */
if (axis == 0)
{
qsort(parent_vpa, sizeof parent_vpa/ sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord_x);
}
if (axis == 1)
{
qsort(parent_vpa, sizeof parent_vpa/ sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord_y);
}
if (axis == 2)
{
qsort(parent_vpa, sizeof parent_vpa/ sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord_z);
}
I'd use an array of function pointers and write:

qsort(parent_vpa, sizeof parent_vpa / sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord[axis]);

the array would be:

typedef int compare_function(const void *, const void *);
compare_function *cmp_coord[] = {
cmp_coord_x, cmp_coord_y, cmp_coord_z
};

(not compiled so beware syntax errors).

--
Ben.
Jun 30 '08 #19

P: n/a
On Mon, 30 Jun 2008 12:04:04 -0700 (PDT), pereges <Br*****@gmail.com>
wrote:
>On Jun 30, 11:13 pm, Keith Thompson <ks...@mib.orgwrote:
>size_t can represent the size in bytes of any object (since it's the
type of the result of the sizeof operator and of the argument to
malloc(). It can therefore represent the size in elements of any
array object, making it suitable for array indices.

The third is a bit more iffy; it depends on what you're counting.

But there are no such guarantees for unsigned long. Consider a
hypothetical system where unsigned long is 32 bits and size_t is 64
bits. You might have objects whose size cannnot be represented as an
unsigned long value.

The question is, why would you want to use unsigned long rather than
size_t?

Suppose I have a structure:

struct mesh
{
unsigned long nvert; /* number of vertices */
unsigned long ntri; /* number of triangles */
vector *vert; /* pointer to array of vertices */
triangle *tri; /* pointer to array of triangles */
};

Now, according to what you are saying nvert and ntri should have data
type size_t instead. In my program its possible for nvert and ntri to
be in millions. I have been adviced that size_t in many cases causes
loss of data, hence I'm skecptical about its use. Also, I would want
to keep things consistent.
SIZE_MAX can be as small as 65K while ULONG_MAX must be at least 4G.
Check your system, or your portability goals, to determine if this a
concern.
Remove del for email
Jul 1 '08 #20

P: n/a
On Jun 30, 11:16 pm, pete <pfil...@mindspring.comwrote:
When I count nodes in linked list, I use long unsigned.
The number of nodes that malloc can generate,
isn't related to size_t.
What if I had to create a link list of pointers to an array ? In that
case the number of nodes in link list can also be size_t. I think you
can apply to a lot of cases by careful analysis.
Jul 1 '08 #21

P: n/a
On Jul 1, 2:04 am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
pereges <Brol...@gmail.comwrites:
Yes, you can.
>
You have your va's and vb's mixed up. I think you wanted:

return (va->coord[0] < vb->coord[0] ? -1 : va->coord[0] vb->coord[0]);
I'd use an array of function pointers and write:

qsort(parent_vpa, sizeof parent_vpa / sizeof *parent_vpa,
sizeof *parent_vpa, cmp_coord[axis]);

the array would be:

typedef int compare_function(const void *, const void *);
compare_function *cmp_coord[] = {
cmp_coord_x, cmp_coord_y, cmp_coord_z
};

(not compiled so beware syntax errors).
Thanks.
Jul 1 '08 #22

P: n/a
pereges wrote:
On Jun 30, 11:16 pm, pete <pfil...@mindspring.comwrote:
>When I count nodes in linked list, I use long unsigned.
The number of nodes that malloc can generate,
isn't related to size_t.

What if I had to create a link list of pointers to an array ? In that
case the number of nodes in link list can also be size_t. I think you
can apply to a lot of cases by careful analysis.
Sure.
I also use long unsigned to count lines in a text stream.

--
pete
Jul 1 '08 #23

P: n/a
On Jul 1, 3:48 pm, pete <pfil...@mindspring.comwrote:
Sure.
I also use long unsigned to count lines in a text stream.
Using long unsigned for lines in text stream is different i guess
because its not related to size_t in anyway. In my case, I'm building
a kdtree for 3d mesh where I have a max_triangles entity which
represents teh threshold of maximum number of triangles that can be
inside a kdtree node. At the most there can be all triangles in the kd
tree node(i.e. the root node) but since number of triangles (ntri, it
was also used to allocate memory for triangle list) was declared as
size_t, I have declared max_triangles also has size_t because it can
take atmost the value ntri.
Jul 1 '08 #24

P: n/a
btw what is appropriate format specifer for size_t type variable ? It
has no problems with any type of integer format specifers( %d %i %lu
%u etc)
Jul 1 '08 #25

P: n/a
pereges wrote:
btw what is appropriate format specifer for size_t type variable ? It
has no problems with any type of integer format specifers( %d %i %lu
%u etc)
%z in C99, %lu and a cast (unsigned long) in C89

Bye, Jojo
Jul 1 '08 #26

P: n/a
On Jul 1, 4:06 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
%z in C99, %lu and a cast (unsigned long) in C89
How is it done with cast ?

Jul 1 '08 #27

P: n/a
pereges wrote:
On Jul 1, 4:06 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
>%z in C99, %lu and a cast (unsigned long) in C89

How is it done with cast ?
....
size_t a
....
printf("a=%lu\n", (unsigned long)a);
....
Jul 1 '08 #28

P: n/a
On Jul 1, 4:11 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
...
size_t a
...
printf("a=%lu\n", (unsigned long)a);
...
I think you meant (unsigned long)&a ?

But why is this caste needed when you are already using %lu ? Often
when I want to use chars as ints, I don't use any caste. I simply do :

char a;
scanf("%d", &a);

And it works.
Jul 1 '08 #29

P: n/a
Joachim Schmitz wrote:
pereges wrote:
>On Jul 1, 4:06 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
>>%z in C99, %lu and a cast (unsigned long) in C89

How is it done with cast ?

...
size_t a
; /* grrr */
...
printf("a=%lu\n", (unsigned long)a);
...

Jul 1 '08 #30

P: n/a
pereges wrote:
On Jul 1, 4:11 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
>...
size_t a
...
printf("a=%lu\n", (unsigned long)a);
...
I think you meant (unsigned long)&a ?
No! To print the address of a use %p
But why is this caste needed when you are already using %lu ? Often
%lu tells printf to expect a long unsigned valie and read it off the stack
(or whatever the parameter passing method of you implementation might be), a
is a size_t which may or may not be the same size, but printf doesn't know,
so it grabs an unsigned long and possible touches something that isn't
allowew or supposed to touch.
when I want to use chars as ints, I don't use any caste. I simply do :

char a;
scanf("%d", &a);

And it works.
%d expects an int, so the scanf reads an int and places it in a char, loos
of precision and sign may occur.

Bye, Jojo
Jul 1 '08 #31

P: n/a
On Jul 1, 4:20 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
No! To print the address of a use %p
But why is this caste needed when you are already using %lu ? Often

%lu tells printf to expect a long unsigned valie and read it off the stack
(or whatever the parameter passing method of you implementation might be), a
is a size_t which may or may not be the same size, but printf doesn't know,
so it grabs an unsigned long and possible touches something that isn't
allowew or supposed to touch.
when I want to use chars as ints, I don't use any caste. I simply do :
char a;
scanf("%d", &a);
And it works.

%d expects an int, so the scanf reads an int and places it in a char, loos
of precision and sign may occur.
I'm sorry I mean while scanning a not printing it :

size_t a;
scanf("%lu", &a);

Is this operation correct ?
Jul 1 '08 #32

P: n/a
pereges wrote:
size_t a;
scanf("%lu", &a);

Is this operation correct ?
No.

long unsigned temp;
size_t a;

scanf("%lu", &temp);
a = temp;
if (a != temp) /*
** Deal with it.
** The return value of scanf also
** should have been checked.
*/

For printf operations,
if you really want to print out your array index,
*and* the array index is also algorithmically constrained
into the minimum guaranteed range of unsigned or long unsigned,
then there's no problem with using one of those.

--
pete
Jul 1 '08 #33

P: n/a
On Jul 1, 2:20 pm, "Joachim Schmitz" <nospam.j...@schmitz-digital.de>
wrote:
pereges wrote:
when I want to use chars as ints, I don't use any caste. I simply do :
If you mean char's as integers, well - they are integers.
char a;
scanf("%d", &a);
And it works.

%d expects an int, so the scanf reads an int and places it in a char, loos
of precision and sign may occur.
That's wrong - it actually invokes undefined behavior.
If you want to do that try
signed char a;
scanf("%hhd", &a);

Recently I learned that this:
int i;
scanf("%d", &i);
invokes undefined behavior with overflow. (ie inputs that their result
INT_MAX or < INT_MIN)
It's unclear to me if this also happends to signed char, but if that
is the case, scanf("%hhd", &a); is potentially invoking undefined
behavior. It's beyond me WHY scanf() is so stupid.
Jul 1 '08 #34

P: n/a
On Jul 1, 2:27 pm, pereges <Brol...@gmail.comwrote:
size_t a;
scanf("%lu", &a);

Is this operation correct ?
With C99, the appropriate way is this:
size_t a;
int i = scanf("%zu", &a);
/* inspect i's value */
With C89 look at pete's reply.
Jul 1 '08 #35

P: n/a
Below , I have just posted some code. Can some one please tell me if
I'm going wrong somewhere with size_t variables ? I noticed that if I
try to check if size_t variable < 0 , then compiler gives a warning.
But there have been situations where my program failed because the
variable assume garbage values.
int parse_sizes(FILE *fp)
{
size_t nvert, ntri;
int rc = 0;

if (fscanf(fp, "%lu%*lu%lu", &nvert, &ntri) != 2)
{
error_report("Error while parsing the file");
rc = 1;
return (rc);
}

if (nvert < MIN_VERTEX_LIMIT || nvert MAX_VERTEX_LIMIT)
{
error_report("Number of vertices out of range");
rc = 1;
return (rc);
}

if (ntri < MIN_TRIANGLE_LIMIT || ntri MAX_TRIANGLE_LIMIT)
{
error_report("Number of triangles out of range");
rc = 1;
return (rc);
}

m_ptr->ntri = ntri;
m_ptr->nvert = nvert;

if (m_ptr->ntri != ntri || m_ptr->nvert != nvert)
{
error_report("Number of vertices out of range");
rc = 1;
return (rc);
}

return (rc);
}
Jul 1 '08 #36

P: n/a
Below , I have just posted some code. Can some one please tell me if
I'm going wrong somewhere with size_t variables ? I noticed that if I
try to check if size_t variable < 0 , then compiler gives a warning.
But there have been situations where my program failed because the
variable assume garbage values.

int parse_sizes(FILE *fp)
{
size_t nvert, ntri;
int rc = 0;

if (fscanf(fp, "%lu%*lu%lu", &nvert, &ntri) != 2)
{
error_report("Error while parsing the file");
rc = 1;
return (rc);
}

if (nvert < MIN_VERTEX_LIMIT || nvert MAX_VERTEX_LIMIT)
{
error_report("Number of vertices out of range");
rc = 1;
return (rc);
}

if (ntri < MIN_TRIANGLE_LIMIT || ntri MAX_TRIANGLE_LIMIT)
{
error_report("Number of triangles out of range");
rc = 1;
return (rc);
}

m_ptr->ntri = ntri;
m_ptr->nvert = nvert;

if (m_ptr->ntri != ntri || m_ptr->nvert != nvert)
{
error_report("Number of vertices and/or number of triangles
out of range");
rc = 1;
return (rc);
}

return (rc);

}
Jul 1 '08 #37

P: n/a
On Jul 1, 3:49 pm, pereges <Brol...@gmail.comwrote:
Below , I have just posted some code. Can some one please tell me if
I'm going wrong somewhere with size_t variables ? I noticed that if I
try to check if size_t variable < 0 , then compiler gives a warning.
I explained to you already why this happends.
unsigned integers cannot have values bellow 0, therefore unsigned
integer < 0 is always false.
But there have been situations where my program failed because the
variable assume garbage values.
The variables assume nothing, please clarify.
>
int parse_sizes(FILE *fp)
{
size_t nvert, ntri;
int rc = 0;

if (fscanf(fp, "%lu%*lu%lu", &nvert, &ntri) != 2)
{
error_report("Error while parsing the file");
rc = 1;
return (rc);
These two lines are useless, just have return 1;
}

if (nvert < MIN_VERTEX_LIMIT || nvert MAX_VERTEX_LIMIT)
Do you intend to change MIN_VERTEX_LIMIT to a value different than 0
in the future? If so, leave it as is and ignore the warning;
If not, remove nvert < MIN_VERTEX_LIMIT.
{
error_report("Number of vertices out of range");
rc = 1;
return (rc);
}

if (ntri < MIN_TRIANGLE_LIMIT || ntri MAX_TRIANGLE_LIMIT)
{
error_report("Number of triangles out of range");
rc = 1;
return (rc);
}

m_ptr->ntri = ntri;
m_ptr->nvert = nvert;
What's the type of m_ptr->ntri, m_ptr->nvert?
>
if (m_ptr->ntri != ntri || m_ptr->nvert != nvert)
{
error_report("Number of vertices and/or number of triangles
out of range");
rc = 1;
return (rc);
}

return (rc);

}
Jul 1 '08 #38

P: n/a
pereges wrote:
Below , I have just posted some code. Can some one please tell me if
I'm going wrong somewhere with size_t variables ? I noticed that if I
try to check if size_t variable < 0 , then compiler gives a warning.
But there have been situations where my program failed because the
variable assume garbage values.
int parse_sizes(FILE *fp)
{
size_t nvert, ntri;
int rc = 0;

if (fscanf(fp, "%lu%*lu%lu", &nvert, &ntri) != 2)
fscanf will write sizeof(long) number of bytes,
to the place where nvert is.
If size_t doesn't have the same representation as long unsigned,
then you have a problem.

--
pete
Jul 1 '08 #39

P: n/a
On Jul 1, 5:56 pm, vipps...@gmail.com wrote:
What's the type of m_ptr->ntri, m_ptr->nvert?
both m_ptr->ntri and m_ptr->nvert are used to allocate arrays. Hence I
have taken them as size_t type.
Jul 1 '08 #40

P: n/a
On Jul 1, 5:56 pm, vipps...@gmail.com wrote:
The variables assume nothing, please clarify.
Well, what I mean to say is that if I had a check in place to see if
the value is below 0 then the program could have been gracefully
terminated after displaying proper error message.
Jul 1 '08 #41

P: n/a
On Jul 1, 5:58 pm, pete <pfil...@mindspring.comwrote:
fscanf will write sizeof(long) number of bytes,
to the place where nvert is.
If size_t doesn't have the same representation as long unsigned,
then you have a problem.
Then what to do in a situation like this ?? or will be better of with
%zu ? I guess that elements the check :

size_t a;
size_t temp;

scanf("%lu", &temp);
a = temp;
if(a != temp)
{
..
}
Jul 1 '08 #42

P: n/a
pereges wrote:
On Jul 1, 5:58 pm, pete <pfil...@mindspring.comwrote:
>fscanf will write sizeof(long) number of bytes,
to the place where nvert is.
If size_t doesn't have the same representation as long unsigned,
then you have a problem.

Then what to do in a situation like this ?? or will be better of with
%zu ?
If you have C99, you can use it.
size_t temp;

scanf("%lu", &temp);
JUST STOP IT ALREADY!

"%lu" IS FOR (long unsigned), THAT'S IT !!!

--
pete
Jul 1 '08 #43

P: n/a
"Joachim Schmitz" <no*********@schmitz-digital.dewrites:
pereges wrote:
btw what is appropriate format specifer for size_t type variable ? It
has no problems with any type of integer format specifers( %d %i %lu
%u etc)
%z in C99, %lu and a cast (unsigned long) in C89
No, it's "%zu" in C99. (Keep in mind that it's the implementation of
printf(), part of the runtime library, that has to support this, not
the compiler.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 1 '08 #44

P: n/a
pereges <Br*****@gmail.comwrites:
[...]
I'm sorry I mean while scanning a not printing it :

size_t a;
scanf("%lu", &a);

Is this operation correct ?
No. It will happen to work if size_t happens to be a typedef for
unsigned long on your system, and it's likely to work if size_t
happens to be the same size as unsigned long.

It will blindly attempt to copy an unsigned long value into a size_t
object (there's no conversion). And that's assuming it doesn't choke
on the size_t* argument where an unsigned long* argument is required.
Undefined behavior.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 1 '08 #45

P: n/a
On Jul 1, 9:34 pm, Keith Thompson <ks...@mib.orgwrote:
No. It will happen to work if size_t happens to be a typedef for
unsigned long on your system, and it's likely to work if size_t
happens to be the same size as unsigned long.

It will blindly attempt to copy an unsigned long value into a size_t
object (there's no conversion). And that's assuming it doesn't choke
on the size_t* argument where an unsigned long* argument is required.
Undefined behavior.
What in your opinion is the best way to perform such range checks ?

Jul 1 '08 #46

P: n/a
I tried to match sizeof(size_t) with sizeof(unsigned short),
sizeof(unsigned long). It is 4 bytes i.e. same as unsigned long int.
Jul 1 '08 #47

P: n/a
pereges <Br*****@gmail.comwrites:
I tried to match sizeof(size_t) with sizeof(unsigned short),
sizeof(unsigned long). It is 4 bytes i.e. same as unsigned long int.
So what?

It happens to match on your system. They're still to be thought of as
distinct types.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 1 '08 #48

P: n/a
pereges <Br*****@gmail.comwrites:
On Jul 1, 9:34 pm, Keith Thompson <ks...@mib.orgwrote:
No. It will happen to work if size_t happens to be a typedef for
unsigned long on your system, and it's likely to work if size_t
happens to be the same size as unsigned long.

It will blindly attempt to copy an unsigned long value into a size_t
object (there's no conversion). And that's assuming it doesn't choke
on the size_t* argument where an unsigned long* argument is required.
Undefined behavior.

What in your opinion is the best way to perform such range checks ?
What range checks are you referring to?

Get the types right first, then worry about range checking.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 1 '08 #49

P: n/a
Keith Thompson wrote:
"Joachim Schmitz" <no*********@schmitz-digital.dewrites:
>pereges wrote:
>>btw what is appropriate format specifer for size_t type variable ?
It has no problems with any type of integer format specifers( %d %i
%lu %u etc)
%z in C99, %lu and a cast (unsigned long) in C89

No, it's "%zu" in C99. (Keep in mind that it's the implementation of
printf(), part of the runtime library, that has to support this, not
the compiler.)
Oops, I didn_t read properly:
z Specifies that a following d, i, o, u, x, or X conversion specifier
applies to a size_t or the corresponding signed integer type argument; or
that a following n conversion specifier applies to a pointer to a signed
integer type corresponding to size_t argument.

I only read: "z .... size_t", thanks for correction.

bye, Jojo
Jul 1 '08 #50

105 Replies

This discussion thread is closed

Replies have been disabled for this discussion.