Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Same structures, different names

Reply
Thread Tools

Same structures, different names

 
 
Ben Bacarisse
Guest
Posts: n/a
 
      04-08-2011
James Kuyper <(E-Mail Removed)> writes:

> On 04/08/2011 07:21 AM, Ben Bacarisse wrote:
>> James Kuyper<(E-Mail Removed)> writes:
>>
>>> On 04/07/2011 10:57 PM, DSF wrote:

>> <snip>
>>>> or operating system, it is off topic. If the question involves the C
>>>> language, example code that includes OS specific calls or compiler
>>>> specific code should not make the question off topic.
>>>
>>> There are OS-specific and compiler-specific forums where such
>>> questions will be answered in a more reliably accurate fashion.

>>
>> Did you miss the "if the question involves the C language" part? I
>> suspect that C questions will be more accurately answered here than in
>> some system-specific group.
>>
>> You might argue that a question that involves C is not necessarily a
>> question about C,

>
> Yes, that's precisely my point.
>
>> ... but then what is the point of the second part of the
>> OP's sentence? It seems to me that the OP is talking about C questions
>> that just happen to be illustrated with system-specific code.

>
> As a general rule, if a question does not involve OS- or
> compiler-specific issues, the code can always be rewritten to make no
> use of or reference to anything involving that particular OS or
> compiler, while retaining the issue you wish to discuss. Such a
> re-write should be performed before posting it here.


I find that overly prescriptive. CS types are usually good at
abstracting general problems from specific instances so I would not
worry about a C issue being expressed in less that standard terms.

> Should such a re-write turn out to be impossible, then that very
> impossibility indicates that the question should be posted to an OS-
> or compiler-specific forum, in order to get a more useful answer.


If you consider the skill-level of many of the questions here I think
you will find that this advice is impractical. If someone is having
trouble with arrays and pointers, re-writing their UI call-backs to
avoid specific UI functions might introduce a whole new set of issues
with the code and you get the classic "well that's not actually the code
I have" reply when you spend time commenting on it.

Don't get me wrong: I appreciate it when someone goes to the trouble of
making a small self-contained standard C example that illustrates their
problem, but I don't think it is possible to insist that everyone do
this or have their question ruled off topic.

--
Ben.
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      04-08-2011
DSF <(E-Mail Removed)> writes:
[...]
> I never understood the overwhelming desire that example code be
> entirely standard-based: There is a comp.std.c group for that.


comp.std.c doesn't mean "discussion of standard C", it means "discussion
of the C standard", i.e., of the documents that define the language.
comp.lang.c is for discussion of the language defined by those
documents.

The line between the two can be hazy, and I usually don't worry about it
too much -- though if somebody asks a general "What's wrong with my
code?" message in comp.std.c, I often suggest that they'll have better
luck in comp.lang.c.

> (True,
> that makes it easier for many to compile and test for themselves, but
> quite often errors are glaringly obvious.) My feeling has always been
> that if a question is based on the features of a particular compiler
> or operating system, it is off topic. If the question involves the C
> language, example code that includes OS specific calls or compiler
> specific code should not make the question off topic.


I think I agree. But if you (that's a generic "you") *can* show us a
portable C program that exhibits the problem, that's going to be
helpful. On the other hand, restructuring the code to make it portable
can sometimes mask the original problem.

Judicious application of common sense is often helpful.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <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"
 
Reply With Quote
 
 
 
 
J. J. Farrell
Guest
Posts: n/a
 
      04-09-2011
DSF wrote:
> ...
>
> static inline struct bar foo2bar(struct foo val)
> {
> struct bar r;
> r.a = val.a;
> r.b = val.b;
> return r;
> }
> ...
>
> The above prototype and function compile fine as C++, but produce
> syntax errors unless "inline" is removed.


It will only produce syntax errors if you're using an old definition of
C, it's valid in C as of 1999.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      04-09-2011
DSF <(E-Mail Removed)> writes:

> On Fri, 08 Apr 2011 12:04:51 +0100, Ben Bacarisse
> <(E-Mail Removed)> wrote:
>
>>DSF <(E-Mail Removed)> writes:

<snip>
>>> static inline struct bar foo2bar(struct foo val)
>>> {
>>> struct bar r;
>>> r.a = val.a;
>>> r.b = val.b;
>>> return r;
>>> }

<snip>
>>> If this is the case, this would cut down on typing, but still
>>> produces more code than I'd like. There wouldn't be a function call,
>>> but the "copy val to r" code would still be created for each "call".

>>
>>I'd have though that depends on the context and the quality of the
>>optimiser but there may be some reason I can't see why it is hard to
>>remove r altogether.

>
> Well, if the compiler can't even be forced to accept foo is the same
> as bar, I don't see how it could optimize away the copying of
> individual elements and just replace foo with bar. If it could do
> that, a simple casting would work.


Optimising usually takes place at a low level after most notions about
types have disappeared. I would have thought the optimiser will simply
see lots of apparently pointless data moves. Of course, if the types
are in fact different in some crucial way, then the moves are needed and
putting the two structs into a union would fail.

<snip>
--
Ben.
 
Reply With Quote
 
DSF
Guest
Posts: n/a
 
      04-09-2011
On Fri, 08 Apr 2011 12:04:51 +0100, Ben Bacarisse
<(E-Mail Removed)> wrote:

>DSF <(E-Mail Removed)> writes:
>
>> On 6 Apr 2011 14:19:41 GMT, Jorgen Grahn <(E-Mail Removed)>
>> wrote:
>>
>>>
>>>Create a
>>>
>>>static inline struct bar foo2bar(struct foo val);
>>>
>>>and let the optimizer deal with it. With a bit of luck the foo2bar()
>>>call just melts away into nothing -- as it should.
>>>
>>>/Jorgen

>>
>> I have it working, but in the pursuit of knowledge I want to know if
>> I understand what you're saying. The actual function would be:
>>
>> static inline struct bar foo2bar(struct foo val)
>> {
>> struct bar r;
>> r.a = val.a;
>> r.b = val.b;
>> return r;
>> }

>
>or you could use a C99 compound literal making the function body simply
>
> return (struct bar){val.a, val.b};
>
>> I then use foo2bar wherever I have a "foo" and a "bar" is needed?

>
>Not quite. Function calls are not "lvalues" which means (in part) that
>you can't take the address of the result. So if you need a bar in some
>context where it's address gets taken, you can use the function call.


I think you meant can't? I understand that.

Such as
int need_bar(struct bar br);

could use
need_bar(foo2bar(foo));

Whilst
int need_bar(struct bar *br);

Would require
struct bar tempbar;
....
tempbar = foo2bar(foo);
need_bar(&tempbar);

>
>> If this is the case, this would cut down on typing, but still
>> produces more code than I'd like. There wouldn't be a function call,
>> but the "copy val to r" code would still be created for each "call".

>
>I'd have though that depends on the context and the quality of the
>optimiser but there may be some reason I can't see why it is hard to
>remove r altogether.


Well, if the compiler can't even be forced to accept foo is the same
as bar, I don't see how it could optimize away the copying of
individual elements and just replace foo with bar. If it could do
that, a simple casting would work.

>
>> Second problem:
>>
>> The above prototype and function compile fine as C++, but produce
>> syntax errors unless "inline" is removed.

>
>Have you been addressing a C++ problem all along or are you trying to
>write this code in a language that is the intersection of valid C and
>valid C++? If so, I am curious about why you need to have this extra
>headache.


No. This is C. But my compiler, like most these days, does C++ as
well. (Sadly, "most these days" consider themselves C++ compilers
that can also do C almost as an afterthought because it's easy enough
to implement both, and you might just need to compile some library
that's written in that "moldy old C" to use with your fantastic C++
code <sarcasm directed at some C++ compiler writers, etc., not C>).

When I got the syntax error, I recompiled it in C++ to confirm
something I dimly remembered from the help file: inline is supported
in C++ but not C in the compiler I use.

From the help file:
Syntax
inline <datatype> <class>_<function> (<parameters>) { <statements>;*}

Description
Use the inline keyword to declare or define C++ inline functions.
Inline functions are best reserved for small, frequently used
functions.

I had hoped that the omission of C in the first statement under
Description was an error. This confirmed it was not.

DSF
 
Reply With Quote
 
Jorgen Grahn
Guest
Posts: n/a
 
      04-09-2011
On Fri, 2011-04-08, Ben Bacarisse wrote:
> DSF <(E-Mail Removed)> writes:
>
>> On 6 Apr 2011 14:19:41 GMT, Jorgen Grahn <(E-Mail Removed)>
>> wrote:
>>
>>>
>>>Create a
>>>
>>>static inline struct bar foo2bar(struct foo val);
>>>
>>>and let the optimizer deal with it. With a bit of luck the foo2bar()
>>>call just melts away into nothing -- as it should.

....

>> I then use foo2bar wherever I have a "foo" and a "bar" is needed?

>
> Not quite. Function calls are not "lvalues" which means (in part) that
> you can't take the address of the result. So if you need a bar in some
> context where it's address gets taken, you can use the function call.


I have to confess that I (when I suggested the inline function) was
influenced by C++. Const references and stuff like that may make the
function call solution more attractive there than in C.

>> If this is the case, this would cut down on typing, but still
>> produces more code than I'd like. There wouldn't be a function call,
>> but the "copy val to r" code would still be created for each "call".

>
> I'd have though that depends on the context and the quality of the
> optimiser but there may be some reason I can't see why it is hard to
> remove r altogether.


And I should also have added: look at the generated code to see if
the function call really gets optimized away (if that matters more
than type safety).

>> The above prototype and function compile fine as C++, but produce
>> syntax errors unless "inline" is removed.


And yes, I was assuming C99.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      04-09-2011
Ben Bacarisse <(E-Mail Removed)> writes:
[...]
> Optimising usually takes place at a low level after most notions about
> types have disappeared. I would have thought the optimiser will simply
> see lots of apparently pointless data moves. Of course, if the types
> are in fact different in some crucial way, then the moves are needed and
> putting the two structs into a union would fail.


At least some optimizers take advantage of language-level information,
including types, to determine what optimizations can be performed.
For example, given:

int i;
long *lp;
/* ... */
i = 42;
*lp = 43;
/* HERE */

a compiler may safely assume that i still has the value 42 at the
point marked "HERE". Without type information, it couldn't make
that assumption.

Some other optimizations do work on lower-level information, for
example replacing machine instruction sequences with sequences that
are equivalent but faster.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <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"
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      04-09-2011
Keith Thompson <(E-Mail Removed)> writes:

> Ben Bacarisse <(E-Mail Removed)> writes:
> [...]
>> Optimising usually takes place at a low level after most notions about
>> types have disappeared. I would have thought the optimiser will simply
>> see lots of apparently pointless data moves. Of course, if the types
>> are in fact different in some crucial way, then the moves are needed and
>> putting the two structs into a union would fail.

>
> At least some optimizers take advantage of language-level information,
> including types, to determine what optimizations can be performed.


Yes, quite right. I should have said "Some optimisations take
place...".

<snip>
--
Ben.
 
Reply With Quote
 
DSF
Guest
Posts: n/a
 
      04-09-2011
On 08 Apr 2011 03:39:24 GMT, Seebs <(E-Mail Removed)> wrote:

>On 2011-04-08, DSF <(E-Mail Removed)> wrote:
>> I never understood the overwhelming desire that example code be
>> entirely standard-based: There is a comp.std.c group for that.

>
>No, there is a comp.std.c group for discussing the standard *itself*,
>not for discussing code conforming with the standard.


Understood.

>> (True,
>> that makes it easier for many to compile and test for themselves, but
>> quite often errors are glaringly obvious.) My feeling has always been
>> that if a question is based on the features of a particular compiler
>> or operating system, it is off topic. If the question involves the C
>> language, example code that includes OS specific calls or compiler
>> specific code should not make the question off topic.

>
>I mostly agree. The problem is that in some cases, you have to know a fair
>bit about a platform to know whether something is an error or not.
>
>Consider the UNIX faq:
>
> if (fd = open("foo", O_RDWR) != -1) {
> write(fd, "hello!\n", 7);
> }
>
>Why does this print hello instead of writing it to a file?
>
>It turns out that you can't easily answer this if you don't know a
>fair bit about Unix, but you don't need to know anything about Unix
>to guess at the problem.
>
>Basically... I figure people are justified in not trying to answer such
>questions, or suggesting that you'll get a better answer in a
>platform-specific group. But I also try to answer them when I notice
>a generic-C answer.


I understand. I would consider that example off topic because
understanding it depends entirely on knowing how "open" and "write"
operate. I'll give an example of a problem I had that illustrates
what I mean. It has non-standard calls in it, but I believe the
problem can be ascertained in spite of them.

Please note that I'm posting this code only as an illustration of my
view of on topic code with OS specific calls. It has been corrected
since and I did perform a Bull Shannon when I discovered the obvious
fault.

The purpose of the code is to take a MS wide "multistring" (a single
character array with zeros delimiting the individual strings and a
single zero to terminate the multistring), separate it into its
individual strings and return them as an array of non-wide strings. It
returns an error status and the number of strings returned (via
stringcount). It is up to the caller to free the strings and the
array itself. A function is provided for that.

The definitions for the error messages (and DWORD) are not included
here, but I believe their meaning is clear.

DWORD MultistringWToStringArray(const wchar_t *multistring,
char **stringarray, int *stringcount)
{
size_t msi, wsl, asl;
size_t sl;
char **temp;
char *astring;
wchar_t *wstring;
DWORD ret = NO_ERROR;

/* returns the length in characters of the longest string in
multistring */
sl = FindLongestStringLengthInMultistringW(multistring) ;
if(sl == 0)
return ST_EMPTY_MULTISTRING;

/* allocate temp space for each individual wide string */
wstring = malloc(sl * sizeof(wchar_t));
if(wstring == NULL)
{
return ST_OUT_OF_MEMORY;
}

stringarray = NULL;
*stringcount = 0;
msi = 0;
while(multistring[msi] != 0)
{
/* allocate space in array for next string pointer */
temp = realloc(stringarray, (*stringcount + 1) *
sizeof(stringarray));
if(temp == NULL)
{
FreeStringArray(stringarray, *stringcount);
ret = ST_OUT_OF_MEMORY;
break;
}
else
stringarray = temp;

/* dstrcpylW is a library function of mine that is a combination of
the wide versions of strcpy and strlen. It copies a wide string from,
in this case, multistring+msi to wstring. It returns the length of
the destination string in characters (wstring) eliminating the need to
traverse wstring twice */
wsl = dstrcpylW(wstring, multistring + msi) + 1;
msi += (wsl * sizeof(wchar_t));

/* Windows API call that converts the wide string to an ASCII string.
if the ASCII string pointer (astring) is NULL, it returns the size
needed to hold the ASCII string */
astring = NULL;
asl = WideCharToMultiByte(CP_ACP, 0, wstring, -1, astring, 0,
NULL, NULL);
if(asl == FALSE)
{
/* WideCharToMultiByte failed, get the error code and clean up */
ret = GetLastError();
FreeStringArray(stringarray, *stringcount);
break;
}
/* else, WideCharToMultiByte returns the length of astring, including
ending zero. */
astring = malloc(asl);
if(astring == NULL)
{
FreeStringArray(stringarray, *stringcount);
ret = ST_OUT_OF_MEMORY;
break;
}
/* Windows API call that converts the wide string wstring to an ASCII
string astring */
WideCharToMultiByte(CP_ACP, 0, wstring, -1, astring, asl,
NULL, NULL);
/* allocate space for the string and copy it to the array */
stringarray[*stringcount] = malloc(asl);
strcpy(stringarray[*stringcount], astring);
free(astring);
(*stringcount)++;
msi++;
}
free(wstring);
return ret;
}

void FreeStringArray(char **stringarray, int stringcount)
{
int i;

for(i = 0; i < stringcount; i++)
free(stringarray[i]);
free(stringarray);
}

I won't state the error here just to see if I am correct and it can
be easily determined, even with non-standard code.

DSF
 
Reply With Quote
 
Seebs
Guest
Posts: n/a
 
      04-10-2011
On 2011-04-09, DSF <(E-Mail Removed)> wrote:
> On 08 Apr 2011 03:39:24 GMT, Seebs <(E-Mail Removed)> wrote:
>>Consider the UNIX faq:
>>
>> if (fd = open("foo", O_RDWR) != -1) {
>> write(fd, "hello!\n", 7);
>> }


>>Basically... I figure people are justified in not trying to answer such
>>questions, or suggesting that you'll get a better answer in a
>>platform-specific group. But I also try to answer them when I notice
>>a generic-C answer.


> I understand. I would consider that example off topic because
> understanding it depends entirely on knowing how "open" and "write"
> operate.


I don't think it does. It really depends on knowing that the code sets
fd to either 0 or 1, not to the return value from open(). You can see
that without any knowledge of the system calls in question...

> DWORD MultistringWToStringArray(const wchar_t *multistring,
> char **stringarray, int *stringcount)
> {
> size_t msi, wsl, asl;
> size_t sl;
> char **temp;
> char *astring;
> wchar_t *wstring;
> DWORD ret = NO_ERROR;
>
> /* returns the length in characters of the longest string in
> multistring */
> sl = FindLongestStringLengthInMultistringW(multistring) ;
> if(sl == 0)
> return ST_EMPTY_MULTISTRING;
>
> /* allocate temp space for each individual wide string */
> wstring = malloc(sl * sizeof(wchar_t));
> if(wstring == NULL)
> {
> return ST_OUT_OF_MEMORY;
> }
>
> stringarray = NULL;
> *stringcount = 0;
> msi = 0;
> while(multistring[msi] != 0)
> {
> /* allocate space in array for next string pointer */
> temp = realloc(stringarray, (*stringcount + 1) *
> sizeof(stringarray));


This is probably wrong but also probably works by happy coincidence, but
really this should be sizeof(*stringarray).

> /* dstrcpylW is a library function of mine that is a combination of
> the wide versions of strcpy and strlen. It copies a wide string from,
> in this case, multistring+msi to wstring. It returns the length of
> the destination string in characters (wstring) eliminating the need to
> traverse wstring twice */
> wsl = dstrcpylW(wstring, multistring + msi) + 1;
> msi += (wsl * sizeof(wchar_t));


I am distrustful of the "sizeof(wchar_t)", because we're indexing multistring
by this, and multstring is already wchar_t sized.

> I won't state the error here just to see if I am correct and it can
> be easily determined, even with non-standard code.


Those two were the only bits that stood out.

-s
--
Copyright 2011, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple import of the same module under different names George Sakkis Python 0 03-11-2010 10:21 AM
Weird issue, same code, same browser, two different apache servers,very different css bluebaron HTML 3 11-04-2009 07:13 PM
running same script on same data on two different machines -->different result Christopher Brewster Python 5 11-14-2008 08:19 PM
Matching attribute names to element names in a different path Carl XML 0 04-01-2004 01:15 PM
same code produces different decimal symbol on different computers with same settings ASP General 2 12-29-2003 02:29 PM



Advertisments