struct enumerating types

L

Lane Straatman

I would like to write a 'struct'. I have a library that is all but
completely inappropriate for this task.

So I'm looking for C code that fills in the gaps between:
#undef whateverkeithsaysfor99compliance
#define whateverkeithsays for99compliance
int main(void
{
struct foo

printf foo
return 0;
}
/*end pseudosource */
I would like one dimension enumerating types, e.g.
foo.int = 9;
foo.char = 'c';
and another dimension with the appropriate printf specifier, e.g.
foo.int.format = "%i";
foo.char.format = "%c";

Q1) How many types exist in C99? LS
 
L

Lane Straatman

Lane Straatman said:
I would like to write a 'struct'. I have a library that is all but
completely inappropriate for this task.

So I'm looking for C code that fills in the gaps between:
#undef whateverkeithsaysfor99compliance
#define whateverkeithsays for99compliance
int main(void
{
struct foo

printf foo
return 0;
}
/*end pseudosource */
I would like one dimension enumerating types, e.g.
foo.int = 9;
foo.char = 'c';
and another dimension with the appropriate printf specifier, e.g.
foo.int.format = "%i";
foo.char.format = "%c";

Q1) How many types exist in C99? LS
Ints range from a short to a long long, so I bet there's at least a dozen
there.

#define nothingatall
typedef struct foo(int, char)
int main(void)
{

struct foo
{
int a;
char b;
};

foo.a = 40;
foo.b = 'k';
printf("%i\n", foo.a);
printf("%c\n", foo.b);
return 0;
}
/* end source */
I can't get this to compile. The offending line begins with 'typedef'. LS
 
K

Keith Thompson

Lane Straatman said:
Ints range from a short to a long long, so I bet there's at least a dozen
there.

"int" is a single type. There are a number of *integer* types.

In C99, there are at least:
char, signed char, unsigned char,
short, unsigned short,
int, unsigned int,
long, unsigned long,
long long, unsigned long long
so that's 11, plus any implementation-defined extended integer types.

The question was "How many types". If you really meant types rather
than just integer types, there's also void, float, double, long
double, and so forth. Add pointer, struct, union, enumeration, and
function types, and the answer is as many as you care to define.
#define nothingatall

You don't use this macro. What is its purpose?
typedef struct foo(int, char)

This doesn't come close enough to making sense for me to be able to
guess what it's supposed to look like. You could probably just drop
that line; there's really no need to declare a typedef for a struct
type. If you have a type "struct foo", you can just call it "struct
foo".
int main(void)
{

struct foo
{
int a;
char b;
};

foo.a = 40;
foo.b = 'k';

You don't have an object named "foo". You don't even have a type
named "foo".
printf("%i\n", foo.a);
printf("%c\n", foo.b);

Calling printf() without a prototype invokes undefined behavior.
The way to get a prototype is to add "#include said:
return 0;
}
/* end source */
I can't get this to compile. The offending line begins with 'typedef'. LS

Here's a correct program that's similar to what you wrote:

#include <stdio.h>
int main(void)
{
struct foo {
int a;
char b;
};
struct foo foo_obj;

foo_obj.a = 40;
foo_obj.b = 'k';
printf("%i\n", foo_obj.a);
printf("%c\n", foo_obj.b);
return 0;
}

Without knowing what you're trying to accomplish, I have no idea
whether this is what you're looking for.

Incidentally, in your previous article you wrote:
| #undef whateverkeithsaysfor99compliance
| #define whateverkeithsays for99compliance

Does that refer to me? Was it an attempt to get my attention?
 
S

santosh

Huh? I can't quite understand what you're trying to say?

Do you mean you want some tool to automatically generate struct
declarations and printf() format specifiers for them? Why would you
want that?
Ints range from a short to a long long, so I bet there's at least a dozen
there.

int is a specific type. Integers are a collection of such types
including char, short, int, long, long long and their unsigned
equivalents. Whether plain char is signed or unsigned is implementation
defined.
#define nothingatall
typedef struct foo(int, char)

What is that supposed to mean. If you want to typedef a struct type do
something like:

typedef struct {
/* members */
} name;

However I find dealing with plain struct types easier than their
typedef'ed versions. YMMV.
int main(void)
{

struct foo
{
int a;
char b;
};

foo.a = 40;
foo.b = 'k';

You can't assign to types anymore than you can assign to int. No memory
is allocated for them. You need to declare one or more objects of type
foo and assign values to them.
printf("%i\n", foo.a);
printf("%c\n", foo.b);
return 0;
}
/* end source */
I can't get this to compile. The offending line begins with 'typedef'. LS

That's because, you're typedef is wrong. Either use typedefs for
structure like I've shown or just use plain structs.
 
L

Lane Straatman

santosh said:
Huh? I can't quite understand what you're trying to say?
Thanks for your reply. The books on my shelf are woefully inadequate to
shepherd me through type definitions in C99.
Mr. Thompson wonders whether I was trying to get his attention with this.
On the one hand, I was trying to be brief in pseudocode. I think that in
order to write this program in a minimally portable fashion, one needs to
have some preprocessor instructions. CBfalconer had these on a related
question; however it was one that was slightly less general than the current
one:
/* Standard defines of operators, usable on C90 up */
#ifndef stdops_h
#define stdops_h
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
/* The following from C99 - must define for C90 */
#include <stdbool.h> /* define bool, true, false */
#include <iso646.h> /* define not, and, or */
#else
#define false 0
#define true 1
typedef int bool;
#define not !
#define and &&
#define or ||
#define xor ^
#endif
#endif
Mr. Thompson added the #undef's:
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
#undef false
#undef true
#undef bool
#define false 0
#define true 1
#define bool int
#endif
, which seemed like something prudential. I probably was trying to get his
attention, not like throwing a brick through the window, but like flagging
something for perusal. I wouldn't have an executable right now without his
help.
Do you mean you want some tool to automatically generate struct
declarations and printf() format specifiers for them? Why would you
want that?
I'd like to write a program that creates a variable of every type I'm likely
to meet in C99, and prints it out. So when I want to know the the
conversion argument for a pointer to an unsigned char, I can re-use the
source.
You can't assign to types anymore than you can assign to int. No memory
is allocated for them. You need to declare one or more objects of type
foo and assign values to them.
I totally fanned on a correct C struct declaration. When I started looking
at ISO C, my windows, C and C++ were all roughly in the same place in my
head. So you start fencing off what is kosher and what is an extension. I
didn't create an object because I thought an object looked like this:

//////////////////////////////////////////////////////////
// The one and only CTja39App object

CTja39App theApp;

//////////////////////////////////////
, which is a leftover from the way MFC instantiates. I'm not the only
person who misunderstands the way the word "object" operates in C.

#ifdef _WIN32
# define FORMAT_LONG_LONG "I64"
#else
# define FORMAT_LONG_LONG "ll"
#endif

#include <stdio.h>
int main(void)
{
struct foo {
int a;
char b;
signed char c;
unsigned char d;
short e;
unsigned short f;
unsigned int g;
long h;
unsigned long i;
__int64 j;
unsigned __int64 k;
}; struct foo foo_obj;

foo_obj.a = 40;
foo_obj.b = 'k';
foo_obj.c = 'k';
foo_obj.d = 'k';
foo_obj.e = 123;
foo_obj.f = 300;
foo_obj.g = 50000;
foo_obj.h = 123123123;
foo_obj.i = 123123123;
foo_obj.j = 123451234512345;
foo_obj.k = 123451234512345;


printf("%i\n", foo_obj.a);
printf("%c\n", foo_obj.b);
printf("%c\n", foo_obj.c);
printf("%uc\n", foo_obj.d);
printf("%hi\n", foo_obj.e);
printf("%hc\n", foo_obj.f);
printf("%ui\n", foo_obj.g);
printf("%li\n", foo_obj.h);
printf("%lu\n", foo_obj.i);
printf("%" FORMAT_LONG_LONG "d\n", foo_obj.j );
printf("%" FORMAT_LONG_LONG "d\n", foo_obj.k );


return 0;
}
Q2) Are the format specifiers right? Obviously my version of long long is
non-standard. The unsigned char conversion seems wrong.

Q3) How would I extend foo to have the conversion characters associated
with their type? If I had a field of ten characters, I could capture
expressions like '"%lu"'. This wouldn't help me with print statements like
that for type of size_t:
printf("%lu", (unsigned long)sizeof(thetype));
, but one problem at a time.
LS
 
L

Lane Straatman

Keith Thompson said:
"int" is a single type. There are a number of *integer* types.

In C99, there are at least:
char, signed char, unsigned char,
short, unsigned short,
int, unsigned int,
long, unsigned long,
long long, unsigned long long
so that's 11, plus any implementation-defined extended integer types.

The question was "How many types". If you really meant types rather
than just integer types, there's also void, float, double, long
double, and so forth. Add pointer, struct, union, enumeration, and
function types, and the answer is as many as you care to define.
On the one hand, you can say there is an arbitrarily large number of types.
But you can classify them into families, much like mathematicians classify
groups. My source beneath enumerates the above types with with one level of
pointer indirection. Sure, you can add asterisks till the cows come home,
but for the purpose of a printf, it's all going to be "%p".
Without knowing what you're trying to accomplish, I have no idea
whether this is what you're looking for.

Incidentally, in your previous article you wrote:
| #undef whateverkeithsaysfor99compliance
| #define whateverkeithsays for99compliance

Does that refer to me? Was it an attempt to get my attention?
I decided the answer to this question is yes and yes. See my reply to
santosh for details.

#ifdef _WIN32
# define FORMAT_LONG_LONG "I64"
#else
# define FORMAT_LONG_LONG "ll"
#endif

#include <stdio.h>
int main(void)
{
char index;
struct foo {
int a;
char b;
signed char c;
unsigned char d;
short e;
unsigned short f;
unsigned int g;
long h;
unsigned long i;
__int64 j;
unsigned __int64 k;
};
struct foo foo_obj;

struct bar {
int * a;
char * b;
signed char * c;
unsigned char * d;
short * e;
unsigned short * f;
unsigned int * g;
long * h;
unsigned long * i;
__int64 * j;
unsigned __int64 * k;
};
struct bar bar_obj;

foo_obj.a = 40;
foo_obj.b = 'k';
foo_obj.c = 'k';
foo_obj.d = 'k';
foo_obj.e = 123;
foo_obj.f = 300;
foo_obj.g = 50000;
foo_obj.h = 123123123;
foo_obj.i = 123123123;
foo_obj.j = 123451234512345;
foo_obj.k = 123451234512345;

printf("%i\n", foo_obj.a);
printf("%c\n", foo_obj.b);
printf("%c\n", foo_obj.c);
printf("%uc\n", foo_obj.d);
printf("%hi\n", foo_obj.e);
printf("%hc\n", foo_obj.f);
printf("%ui\n", foo_obj.g);
printf("%li\n", foo_obj.h);
printf("%lu\n", foo_obj.i);
printf("%" FORMAT_LONG_LONG "d\n", foo_obj.j );
printf("%" FORMAT_LONG_LONG "d\n", foo_obj.k );


bar_obj.a = & foo_obj.a;
bar_obj.b = & foo_obj.b;
bar_obj.c = & foo_obj.c;
bar_obj.d = & foo_obj.d;
bar_obj.e = & foo_obj.e;
bar_obj.f = & foo_obj.f;
bar_obj.g = & foo_obj.g;
bar_obj.h = & foo_obj.h;
bar_obj.i = & foo_obj.i;
bar_obj.j = & foo_obj.j;
bar_obj.k = & foo_obj.k;

printf("%p\n", bar_obj.a);
printf("%p\n", bar_obj.b);
printf("%p\n", bar_obj.c);
printf("%p\n", bar_obj.d);
printf("%p\n", bar_obj.e);
printf("%p\n", bar_obj.f);
printf("%p\n", bar_obj.g);
printf("%p\n", bar_obj.h);
printf("%p\n", bar_obj.i);
printf("%p\n", bar_obj.j);
printf("%p\n", bar_obj.k);

/*
for (index = 'b'; index <= 'k'; ++ index)
{
bar_obj.index = & foo_obj.index
printf("%p\n", bar_obj.index);
}
*/
return 0;
}
Q4) Why didn't my commented-out loop work? LS
 
K

Keith Thompson

Lane Straatman said:
On the one hand, you can say there is an arbitrarily large number of types.
But you can classify them into families, much like mathematicians classify
groups. My source beneath enumerates the above types with with one level of
pointer indirection. Sure, you can add asterisks till the cows come home,
but for the purpose of a printf, it's all going to be "%p".

I decided the answer to this question is yes and yes. See my reply to
santosh for details.

If you want to address something to me, please do so; I had no clue
what you meant by "whateverkeithsaysfor99compliance". But in general
there's no need to address questions here to any one person.
#ifdef _WIN32
# define FORMAT_LONG_LONG "I64"
#else
# define FORMAT_LONG_LONG "ll"
#endif

#include <stdio.h>
int main(void)
{
char index;
struct foo {
int a;
char b;
signed char c;
unsigned char d;
short e;
unsigned short f;
unsigned int g;
long h;
unsigned long i;
__int64 j;
unsigned __int64 k;
};
struct foo foo_obj;

You conditionalize the FORMAT_LONG_LONG based on _WIN32, but then you
unconditionally declare members of type __int64, which is a
non-standard type.

But __int64 and long long aren't necessarily equivalent; long long is
*at least* 64 bits.
struct bar {
int * a;
char * b;
signed char * c;
unsigned char * d;
short * e;
unsigned short * f;
unsigned int * g;
long * h;
unsigned long * i;
__int64 * j;
unsigned __int64 * k;
};
struct bar bar_obj;

[Multiple printf statements snipped]

Perhaps someone else will have the patience to jump back and forth
between your type declarations and your printf statements and check
whether they're correct.

One observation: the "%p" format works only for type void*. To print
any other pointer type, you need to convert it explicitly. (It's
likely to work if you don't, but it's undefined behavior).

some_type *ptr;
printf("ptr = %p\n", (void*)ptr);
/*
for (index = 'b'; index <= 'k'; ++ index)
{
bar_obj.index = & foo_obj.index
printf("%p\n", bar_obj.index);
}
*/
return 0;
}
Q4) Why didn't my commented-out loop work? LS

For one thing, bar_obj doesn't have a member named "index". Your
compiler's error message (which you didn't show us) should have made
this clear. (If bar_obj does have a member named "index", then you
didn't show us your actual code.)

In general, questions of the form "Why doesn't <whatever> work?"
aren't terribly useful. Tell us *how* it didn't work, and what you
expected it to do.
 
S

santosh

Lane said:
Thanks for your reply. The books on my shelf are woefully inadequate to
shepherd me through type definitions in C99.

Well, the working draft of the current C standard from ISO's website
combined with the second edition of The C Programming Language should
be enough for all predefined types.

I'd like to write a program that creates a variable of every type I'm likely
to meet in C99, and prints it out. So when I want to know the the
conversion argument for a pointer to an unsigned char, I can re-use the
source.

Strictly speaking, you're likely to meet more types than you can
possibly print out. Though the predefined types in C are not numerous,
programs can create any number of composite and derived types.

The printf() and scanf() format specifiers for all the built-in types
are given in the standard, and should be available in any C99 standard
library reference, like the one in dinkumware.com. They're not more
than about fifty and don't take much to learn.

Format specifiers for the types in stdint.h are available in
inttypes.h, (both C99).

#ifdef _WIN32
# define FORMAT_LONG_LONG "I64"
#else
# define FORMAT_LONG_LONG "ll"
#endif

#include <stdio.h>
int main(void)
{
struct foo {
int a;
char b;
signed char c;
unsigned char d;
short e;
unsigned short f;
unsigned int g;
long h;
unsigned long i;
__int64 j;

Non-standard type. Use long long.
unsigned __int64 k;

Ditto. Use unsigned long long.
}; struct foo foo_obj;

foo_obj.a = 40;
foo_obj.b = 'k';
foo_obj.c = 'k';
foo_obj.d = 'k';
foo_obj.e = 123;
foo_obj.f = 300;
foo_obj.g = 50000;
foo_obj.h = 123123123;
foo_obj.i = 123123123;
foo_obj.j = 123451234512345;
foo_obj.k = 123451234512345;


printf("%i\n", foo_obj.a);
printf("%c\n", foo_obj.b);
printf("%c\n", foo_obj.c);

Use %hhd
printf("%uc\n", foo_obj.d);

Use %hhu
printf("%hi\n", foo_obj.e);
printf("%hc\n", foo_obj.f);

Use %hu
printf("%ui\n", foo_obj.g);
printf("%li\n", foo_obj.h);
printf("%lu\n", foo_obj.i);
printf("%" FORMAT_LONG_LONG "d\n", foo_obj.j );
printf("%" FORMAT_LONG_LONG "d\n", foo_obj.k );

Just use %ll for long long values. Modify with u, d, i, x, X, o as
applicable.
return 0;
}

Compiling your code as given above produces:

~$ gcc -Wall -Wextra -std=c99 -pedantic -O4 -o t t.c
t.c: In function 'main':
t.c:20: error: syntax error before '__int64'
t.c:20: warning: no semicolon at end of struct or union
t.c:24: warning: ISO C forbids nested functions
t.c:24: error: syntax error before 'k'
t.c: At top level:
t.c:28: warning: ISO C does not allow extra ';' outside of a function
t.c:30: error: syntax error before '.' token
t.c:43: error: syntax error before string constant
t.c:43: warning: type defaults to 'int' in declaration of 'printf'
t.c:43: error: conflicting types for 'printf'
t.c:43: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:43: warning: data definition has no type or storage class
t.c:44: error: syntax error before string constant
t.c:44: warning: type defaults to 'int' in declaration of 'printf'
t.c:44: error: conflicting types for 'printf'
t.c:44: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:44: warning: data definition has no type or storage class
t.c:45: error: syntax error before string constant
t.c:45: warning: type defaults to 'int' in declaration of 'printf'
t.c:45: error: conflicting types for 'printf'
t.c:45: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:45: warning: data definition has no type or storage class
t.c:46: error: syntax error before string constant
t.c:46: warning: type defaults to 'int' in declaration of 'printf'
t.c:46: error: conflicting types for 'printf'
t.c:46: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:46: warning: data definition has no type or storage class
t.c:47: error: syntax error before string constant
t.c:47: warning: type defaults to 'int' in declaration of 'printf'
t.c:47: error: conflicting types for 'printf'
t.c:47: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:47: warning: data definition has no type or storage class
t.c:48: error: syntax error before string constant
t.c:48: warning: type defaults to 'int' in declaration of 'printf'
t.c:48: error: conflicting types for 'printf'
t.c:48: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:48: warning: data definition has no type or storage class
t.c:51: error: syntax error before string constant
t.c:51: warning: type defaults to 'int' in declaration of 'printf'
t.c:51: error: conflicting types for 'printf'
t.c:51: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:51: warning: data definition has no type or storage class
t.c:52: error: syntax error before string constant
t.c:52: warning: type defaults to 'int' in declaration of 'printf'
t.c:52: error: conflicting types for 'printf'
t.c:52: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:52: warning: data definition has no type or storage class
t.c:53: error: syntax error before string constant
t.c:53: warning: type defaults to 'int' in declaration of 'printf'
t.c:53: error: conflicting types for 'printf'
t.c:53: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:53: warning: data definition has no type or storage class
t.c:54: error: syntax error before string constant
t.c:54: warning: type defaults to 'int' in declaration of 'printf'
t.c:54: error: conflicting types for 'printf'
t.c:54: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:54: warning: data definition has no type or storage class
t.c:55: error: syntax error before string constant
t.c:55: warning: type defaults to 'int' in declaration of 'printf'
t.c:55: error: conflicting types for 'printf'
t.c:55: note: a parameter list with an ellipsis can't match an empty
parameter name list declaration
t.c:55: warning: data definition has no type or storage class
Q3) How would I extend foo to have the conversion characters associated
with their type? If I had a field of ten characters, I could capture
expressions like '"%lu"'. This wouldn't help me with print statements like
that for type of size_t:
printf("%lu", (unsigned long)sizeof(thetype));
, but one problem at a time.

Just define macros as inttypes.h does. Most people can type from
memory, but whatever floats your boat.

PS. For size_t C99 defines the %z format specifier.
 
L

Lane Straatman

santosh said:
Lane Straatman wrote:
Well, the working draft of the current C standard from ISO's website
combined with the second edition of The C Programming Language should
be enough for all predefined types.
K&R2 knows nothing of C99, which one would expect from the 1988 copyright.
I don't know if this is what you meant for the ISO reference, but this
resource is fantastic:
http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf
The changes from C89 and from C99 are emphasized. I think this might have
been the reference that Keith Thompson was thinking of with what he called
"change bars" when he advised someone that n1124.pdf had these changes
highlighted. I find no such changes marked in n1124.pdf .
Strictly speaking, you're likely to meet more types than you can
possibly print out. Though the predefined types in C are not numerous,
programs can create any number of composite and derived types.
It's the predefined types in C99 that I'm after.
The printf() and scanf() format specifiers for all the built-in types
are given in the standard, and should be available in any C99 standard
library reference, like the one in dinkumware.com. They're not more
than about fifty and don't take much to learn.
I just went through n1124.pdf and got nothing. If there's fifty predefined
types, then their format specifiers would be a large enough topic to include
in the index, where I find no reference.
Format specifiers for the types in stdint.h are available in
inttypes.h, (both C99).
But they look like this:
#define PRIiLEAST8 "i"
#define PRIiLEAST16 "i"
#define PRIiLEAST32 "i"
#define PRIiLEAST64 "lli"
It doesn't really help.

#include <stdio.h>
int main(void)
{
struct foo
{
int a;
char b;
signed char c;
unsigned char d;
short e;
unsigned short f;
unsigned int g;
long h;
unsigned long i;
};
struct foo foo_obj;

foo_obj.a = 40;
foo_obj.b = 'k';
foo_obj.c = 'k';
foo_obj.d = 'k';
foo_obj.e = 123;
foo_obj.f = 300;
foo_obj.g = 50000;
foo_obj.h = 123123123;
foo_obj.i = 123123123;

printf("%hhd\n", foo_obj.a);
printf("%hhd\n", foo_obj.b);
printf("%hhd\n", foo_obj.c);
printf("%hhu\n", foo_obj.d);
printf("%hu\n", foo_obj.e);
printf("%hu\n", foo_obj.f);
printf("%ud\n", foo_obj.g);
printf("%ld\n", foo_obj.h);
printf("%lu\n", foo_obj.i);
return 0;
}
I still think my specifier for unsigned int is wrong. It prints '50000i'.
I'd guess I'm in undefined behavior. I took out the long long, because
there's no standard way for me to do it, with what I'm running.
Compiling your code as given above produces:
[ 40 errors and warnings]
Getting 40 errors and warnings would seem to be the acme of sloppiness. I
noticed a small error at the dinkumware site in the text:
<inttypes.h> -- for for converting various integer types
The extra 'for' is obviously an erratum. If you add an extra 'for' in a for
loop, MSVC gives 5 errors and warnings:
tja41.c(68) : error C2059: syntax error : 'for'
tja41.c(68) : warning C4552: '<=' : operator has no effect; expected
operator with side-effect
tja41.c(68) : error C2143: syntax error : missing ';' before ')'
tja41.c(74) : error C2059: syntax error : 'return'
tja41.c(75) : error C2059: syntax error : '}'
Little things can have horrible-sounding error-cascades.
Just define macros as inttypes.h does. Most people can type from
memory, but whatever floats your boat.
I think the solution for me is to get cygwin, which I've installed while
writing this post. I wish I knew something about unix. LS
 
L

Lane Straatman

Keith Thompson said:
If you want to address something to me, please do so; I had no clue
what you meant by "whateverkeithsaysfor99compliance". But in general
there's no need to address questions here to any one person.
Usually when I post, there's the first wave of corrections and then someone
like you or Heathfield corrects the corrections about halfway through. If
it's something with preprocessor instructions, yours is often the last word.
But __int64 and long long aren't necessarily equivalent; long long is
*at least* 64 bits. Gotcha.

One observation: the "%p" format works only for type void*. To print
any other pointer type, you need to convert it explicitly. (It's
likely to work if you don't, but it's undefined behavior).

some_type *ptr;
printf("ptr = %p\n", (void*)ptr); Gotcha.


For one thing, bar_obj doesn't have a member named "index". Your
compiler's error message (which you didn't show us) should have made
this clear. (If bar_obj does have a member named "index", then you
didn't show us your actual code.)

In general, questions of the form "Why doesn't <whatever> work?"
aren't terribly useful. Tell us *how* it didn't work, and what you
expected it to do.
The error was precisely what you said. Since, in the following:
for (index = 'b'; index <= 'k'; ++ index)
{
//bar_obj.index = & foo_obj.index
printf("%c\t", index);
}
, index assumes the letters 'b' through 'k', I thought I could loop through
the struct members this way. Apparently it's illegal.
Q5) How does a person loop through the members of a struct? LS
 
K

Keith Thompson

Lane Straatman said:
K&R2 knows nothing of C99, which one would expect from the 1988 copyright.

Of course, but it's still a valuable resource for C90, particularly in
conjunction with the errata page at
I don't know if this is what you meant for the ISO reference, but this
resource is fantastic:
http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf

Yes, that's good too.
The changes from C89 and from C99 are emphasized.

To be clear, it covers the changes made in C89/C90 (relative to K&R
C), and the changes made in C99 (relative to C90; it doesn't, as far
as I know, mention any post-C99 changes. (I'm sure that's what you
meant.)
I think this might have
been the reference that Keith Thompson was thinking of with what he called
"change bars" when he advised someone that n1124.pdf had these changes
highlighted.

No, I meant n1124.pdf.
I find no such changes marked in n1124.pdf .

The first few change bars are:

Pages xi, xi, and xiii
3.4.4
5.1.2.3p12
5.2.2p1
5.2.4.2.2p4

There are many others. Is your PDF viewer displaying them properly?

[snip]
I just went through n1124.pdf and got nothing. If there's fifty predefined
types, then their format specifiers would be a large enough topic to include
in the index, where I find no reference.

The format specifiers for the *printf() and *scanf() functions are
fully described in 7.19.6.1 and 7.19.6.2, respectively.

[snip]
 
K

Keith Thompson

Lane Straatman said:
The error was precisely what you said. Since, in the following:
for (index = 'b'; index <= 'k'; ++ index)
{
//bar_obj.index = & foo_obj.index
printf("%c\t", index);
}
, index assumes the letters 'b' through 'k', I thought I could loop through
the struct members this way. Apparently it's illegal.
Q5) How does a person loop through the members of a struct? LS

Identifiers, including names of struct members, no longer exist when
your program is running. If you wanted to loop through the members,
you should have declared an array rather than a struct. See also FAQ
2.15, <http://www.c-faq.com/>.
 
L

Lane Straatman

Keith Thompson said:
Identifiers, including names of struct members, no longer exist when
your program is running. If you wanted to loop through the members,
you should have declared an array rather than a struct. See also FAQ
2.15, <http://www.c-faq.com/>.
An array composed of differing types? LS
 
L

Lane Straatman

To be clear, it covers the changes made in C89/C90 (relative to K&R
C), and the changes made in C99 (relative to C90; it doesn't, as far
as I know, mention any post-C99 changes. (I'm sure that's what you
meant.)
[continues on n1124]
The first few change bars are:

Pages xi, xi, and xiii
3.4.4
5.1.2.3p12
5.2.2p1
5.2.4.2.2p4

There are many others. Is your PDF viewer displaying them properly?
I don't think I'll ever know the answer to this question because when I
started playing with the menus, it prompted me for an update, which I took.
At any rate, I _do_ see the change bars now. They aren't as dramatic as
they sound, indeed they are the '|' character in the right margin. For my
current endeavors, the "Rationale" doc is much more categorical. I tried to
find the section that would correspond to the screenshot I took of n1124,
but the numberings were different:
http://www.billfordx.net/screendumps/cstuff_6.htm

The format specifiers for the *printf() and *scanf() functions are
fully described in 7.19.6.1 and 7.19.6.2, respectively.
I'll get on that. LS
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top