473,466 Members | 1,381 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

question about 2.6 in the faq

I was confused about part 2.6 in the comp.lang.c. FAQ.

2.6 ... <cut>
Another possibility is to declare the variable-size element very
large, rather than very small; in the case of the above example:

...
char namestr[MAXSIZE];

where MAXSIZE is larger than any name which will be stored.
However, it looks like this technique is disallowed by a strict
interpretation of the Standard as well. Furthermore, either of
these "chummy" structures must be used with care, since the
programmer knows more about their size than the compiler does.
I thought it was valid to have arrays of characters in a struct. Am I
missing
something? I realize the intent of the FAQ was to explain how not to
simulate
variable-length arrays.

Thanks for any explanation,
Mick
Oct 20 '08 #1
7 1347
On Oct 20, 9:44 pm, myheartinamerica <myheartinamer...@gmail.com>
wrote:
I was confused about part 2.6 in the comp.lang.c. FAQ.

2.6 ... <cut>
Another possibility is to declare the variable-size element very
large, rather than very small; in the case of the above example:

...
char namestr[MAXSIZE];

where MAXSIZE is larger than any name which will be stored.
However, it looks like this technique is disallowed by a strict
interpretation of the Standard as well. Furthermore, either of
these "chummy" structures must be used with care, since the
programmer knows more about their size than the compiler does.

I thought it was valid to have arrays of characters in a struct. Am I
missing something?
You can have arrays in structs.
The reason the FAQ says this is not valid is because the context is
close to this

char (*p)[42] = malloc(30);
if(p == NULL) return 0;
strcpy(p[0], "hello world");
puts(p[0]);

This will probably compile and "work" as expected by any C
implementation (including the right headers, main, et cetera).
However, p[0] is a char[42]; we've only allocated for a char[30].
Strictly speaking, using p[0] in any way invokes undefined behavior,
just like using a pointer to any object where not enough memory for
that object is allocated is UB.
Oct 20 '08 #2
myheartinamerica <my**************@gmail.comwrites:
I was confused about part 2.6 in the comp.lang.c. FAQ.

2.6 ... <cut>
Another possibility is to declare the variable-size element very
large, rather than very small; in the case of the above example:

...
char namestr[MAXSIZE];

where MAXSIZE is larger than any name which will be stored.
However, it looks like this technique is disallowed by a strict
interpretation of the Standard as well. Furthermore, either of
these "chummy" structures must be used with care, since the
programmer knows more about their size than the compiler does.
I thought it was valid to have arrays of characters in a struct. Am I
missing
something? I realize the intent of the FAQ was to explain how not to
simulate
variable-length arrays.
If you'll look at the immediately following code, the idea is to
allocate *less* than the size of the struct, on the assumption that
you'll be ok if you don't use array elements beyond the allocated
size.

Speaking of variable length, it looks like you're writing long lines
and then something is wrapping them; the result is alternating long
and short lines, which can be difficult to read. If you'll keep your
lines below about 70 columns in the first place, this shouldn't
happen.

Compare:
I thought it was valid to have arrays of characters in a struct. Am I
missing
something? I realize the intent of the FAQ was to explain how not to
simulate
variable-length arrays.
versus:
I thought it was valid to have arrays of characters in a struct. Am
I missing something? I realize the intent of the FAQ was to explain
how not to simulate variable-length arrays.
--
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"
Oct 20 '08 #3
In article
<35**********************************@s1g2000prg.g ooglegroups.com>,
vi******@gmail.com wrote:
On Oct 20, 9:44 pm, myheartinamerica <myheartinamer...@gmail.com>
wrote:
I was confused about part 2.6 in the comp.lang.c. FAQ.

2.6 ... <cut>
Another possibility is to declare the variable-size element very
large, rather than very small; in the case of the above example:

...
char namestr[MAXSIZE];

where MAXSIZE is larger than any name which will be stored.
However, it looks like this technique is disallowed by a strict
interpretation of the Standard as well. Furthermore, either of
these "chummy" structures must be used with care, since the
programmer knows more about their size than the compiler does.

I thought it was valid to have arrays of characters in a struct. Am I
missing something?

You can have arrays in structs.
The reason the FAQ says this is not valid is because the context is
close to this

char (*p)[42] = malloc(30);
if(p == NULL) return 0;
strcpy(p[0], "hello world");
puts(p[0]);

This will probably compile and "work" as expected by any C
implementation (including the right headers, main, et cetera).
However, p[0] is a char[42]; we've only allocated for a char[30].
Strictly speaking, using p[0] in any way invokes undefined behavior,
just like using a pointer to any object where not enough memory for
that object is allocated is UB.
Just to give a more obviously UB example that as you hint at, this
allocates space for only the first int in the struct:

struct S { int i, j; };

S* s = malloc( sizeof (int) );
s->i = 1234; // UB
printf( "%d\n", s->i ); // UB

Perhaps one justification a compiler could provide is that S has a
stricter alignment requirement than int, and since the size passed to
malloc is less than sizeof (S), it isn't required to align the memory
sufficiently for S.
Oct 20 '08 #4
blargg wrote:
>
Just to give a more obviously UB example that as you hint at, this
allocates space for only the first int in the struct:

struct S { int i, j; };
struct
S* s = malloc( sizeof (int) );
s->i = 1234; // UB
printf( "%d\n", s->i ); // UB

Perhaps one justification a compiler could provide is that S has a
stricter alignment requirement than int, and since the size passed to
malloc is less than sizeof (S), it isn't required to align the memory
sufficiently for S.
There was a huge debate about this in c.l.c. about fifteen years
ago, and the eventual consensus was that all alignment requirements
must be met even if their possible violation is untestable.

But there's another problem, not involving alignment. Since the
compiler "knows" that `s' is either NULL or points to a `struct S'
object, the compiler is free to generate code that accesses `s->j'
even if you and I can't see any good reason for it to do so. If
the memory that ought to hold `s->j' doesn't actually exist, the
consequences are unpredictable. (Yes, I once debugged just such a
situation: The details were a little different, but when a "short"
struct instance happened to fall close to the end of a memory page
and the compiler decided to pre-fetch a non-existent field several
lines before the program wanted to use it, all Hell broke loose.)

--
Er*********@sun.com
Oct 20 '08 #5
In article <1224538652.646588@news1nwk>, Eric Sosman <Er*********@sun.com>
wrote:
blargg wrote:

Just to give a more obviously UB example that as you hint at, this
allocates space for only the first int in the struct:

struct S { int i, j; };
struct
S* s = malloc( sizeof (int) );
s->i = 1234; // UB
printf( "%d\n", s->i ); // UB

Perhaps one justification a compiler could provide is that S has a
stricter alignment requirement than int, and since the size passed to
malloc is less than sizeof (S), it isn't required to align the memory
sufficiently for S.

There was a huge debate about this in c.l.c. about fifteen years
ago, and the eventual consensus was that all alignment requirements
must be met even if their possible violation is untestable.
Not sure what you mean "even if their possible violation is untestable".
Are you saying that malloc(1) must align for example to 8 bytes on
platforms where double has an 8-byte alignment requirement, even though a
sizeof(double)>1 on such a platform? About the only useful consequence of
that seems to be that you could do

double* d = malloc(1);
char* c = (char*) d;
// use *c...
free( c ); // well-defined
But there's another problem, not involving alignment. Since the
compiler "knows" that `s' is either NULL or points to a `struct S'
object, the compiler is free to generate code that accesses `s->j'
even if you and I can't see any good reason for it to do so. If
the memory that ought to hold `s->j' doesn't actually exist, the
consequences are unpredictable. (Yes, I once debugged just such a
situation: The details were a little different, but when a "short"
struct instance happened to fall close to the end of a memory page
and the compiler decided to pre-fetch a non-existent field several
lines before the program wanted to use it, all Hell broke loose.)
Your example sounds more like this:

short* p = <logical address that's not yet valid to access>;

// provide physical backing for address by messing with page tables
// ...

// now access memory
*p = 1234;

where the compiler is free to move the store to p earlier (and thus cause
a crash), since p isn't declared to point to a volatile type as it should
be.
Oct 21 '08 #6
blargg wrote:
In article <1224538652.646588@news1nwk>, Eric Sosman <Er*********@sun.com>
wrote:
>blargg wrote:
>>Just to give a more obviously UB example that as you hint at, this
allocates space for only the first int in the struct:

struct S { int i, j; };
struct
>> S* s = malloc( sizeof (int) );
s->i = 1234; // UB
printf( "%d\n", s->i ); // UB

Perhaps one justification a compiler could provide is that S has a
stricter alignment requirement than int, and since the size passed to
malloc is less than sizeof (S), it isn't required to align the memory
sufficiently for S.
There was a huge debate about this in c.l.c. about fifteen years
ago, and the eventual consensus was that all alignment requirements
must be met even if their possible violation is untestable.

Not sure what you mean "even if their possible violation is untestable".
Are you saying that malloc(1) must align for example to 8 bytes on
platforms where double has an 8-byte alignment requirement, even though a
sizeof(double)>1 on such a platform? About the only useful consequence of
that seems to be that you could do

double* d = malloc(1);
char* c = (char*) d;
// use *c...
free( c ); // well-defined
Yes, that's my report of the consensus. The fragment you
show has well-defined behavior (assuming "use *c" makes proper
provision for the case `d == NULL'). Note that "the fragment
works" is a little weaker than the consensus opinion: All it
shows is that malloc() returns a pointer that can be converted
to `double*' without loss of information. My own take on the
consensus was along the lines of "That which has no observable
consequences does not exist" -- the philosophy majors are welcome
to shred me on this one -- but I have no desire to reawaken the
sterile argument, just to report its existence and its outcome.
> But there's another problem, not involving alignment. Since the
compiler "knows" that `s' is either NULL or points to a `struct S'
object, the compiler is free to generate code that accesses `s->j'
even if you and I can't see any good reason for it to do so. If
the memory that ought to hold `s->j' doesn't actually exist, the
consequences are unpredictable. (Yes, I once debugged just such a
situation: The details were a little different, but when a "short"
struct instance happened to fall close to the end of a memory page
and the compiler decided to pre-fetch a non-existent field several
lines before the program wanted to use it, all Hell broke loose.)

Your example sounds more like this:

short* p = <logical address that's not yet valid to access>;

// provide physical backing for address by messing with page tables
// ...

// now access memory
*p = 1234;

where the compiler is free to move the store to p earlier (and thus cause
a crash), since p isn't declared to point to a volatile type as it should
be.
Since C provides no mechanism to produce a "logical address
that's not yet valid to access," I'm not sure what to make of
your example. The bug I debugged (with two other people, the
three of us contributing different skills to the job) did not
involve the setting of any pointer to an invalid address. Rather,
the pointer was to a perfectly valid address -- but not to an
address that was valid for a full-fledged `struct S'.

--
Eric Sosman
es*****@ieee-dot-org.invalid
Oct 21 '08 #7
On Oct 20, 2:08*pm, Keith Thompson <ks...@mib.orgwrote:
Speaking of variable length, it looks like you're writing long lines
and then something is wrapping them; the result is alternating long
and short lines, which can be difficult to read. *If you'll keep your
lines below about 70 columns in the first place, this shouldn't
happen.

Compare:
I thought it was valid to have arrays of characters in a struct. Am I
missing
something? I realize the intent of the FAQ was to explain how not to
simulate
variable-length arrays.

versus:
I thought it was valid to have arrays of characters in a struct. Am
I missing something? I realize the intent of the FAQ was to explain
how not to simulate variable-length arrays.
I wholeheartedly agree that it was unreadable. I wrote my response in
Vim wrapped at 80 columns. Then I pasted it into the web interface of
Google Groups, which doesn't seem to show you where it will wrap.
Google Groups lets you compose lines that are wrapped by the size of
the input box. If I resize my browser window, it resizes where the
lines are wrapped.

While I appreciate the convenience of Google Groups, I question its
impact on Usenet readability and quality.

Anyways, I intend this to be the last message I write from the web
interface.

Thanks for your response,
Mick Beaver
Oct 29 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Mohammed Mazid | last post by:
Can anyone please help me on how to move to the next and previous question? Here is a snippet of my code: Private Sub cmdNext_Click() End Sub Private Sub cmdPrevious_Click() showrecord
3
by: Stevey | last post by:
I have the following XML file... <?xml version="1.0"?> <animals> <animal> <name>Tiger</name> <questions> <question index="0">true</question> <question index="1">true</question> </questions>
7
by: nospam | last post by:
Ok, 3rd or is it the 4th time I have asked this question on Partial Types, so, since it seems to me that Partial Types is still in the design or development stages at Microsoft, I am going to ask...
3
by: Ekqvist Marko | last post by:
Hi, I have one Access database table including questions and answers. Now I need to give answer id automatically to questionID column. But I don't know how it is best (fastest) to do? table...
10
by: glenn | last post by:
I am use to programming in php and the way session and post vars are past from fields on one page through to the post page automatically where I can get to their values easily to write to a...
10
by: Rider | last post by:
Hi, simple(?) question about asp.net configuration.. I've installed ASP.NET 2.0 QuickStart Sample successfully. But, When I'm first start application the follow message shown. ========= Server...
53
by: Jeff | last post by:
In the function below, can size ever be 0 (zero)? char *clc_strdup(const char * CLC_RESTRICT s) { size_t size; char *p; clc_assert_not_null(clc_strdup, s); size = strlen(s) + 1;
56
by: spibou | last post by:
In the statement "a *= expression" is expression assumed to be parenthesized ? For example if I write "a *= b+c" is this the same as "a = a * (b+c)" or "a = a * b+c" ?
2
by: Allan Ebdrup | last post by:
Hi, I'm trying to render a Matrix question in my ASP.Net 2.0 page, A matrix question is a question where you have several options that can all be rated according to several possible ratings (from...
3
by: Zhang Weiwu | last post by:
Hello! I wrote this: ..required-question p:after { content: "*"; } Corresponding HTML: <div class="required-question"><p>Question Text</p><input /></div> <div...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.