C sizeof problem

Started by
43 comments, last by _the_phantom_ 15 years, 9 months ago
Quote:His code is extremely bad anyway, even for C.


If that is "extremely bad", please show us your solution written in C. We would like to learn great code. It needs to be written in C. Not C++, not D, C.
Advertisement
Quote:Original post by dashurc
Is the XOR swap actually faster though??? I was always under the impression (from what I'd been taught) that it was useful on embedded systems when you were working under extremely tight memory constraints (where you might not even have memory to put the temp variable on the stack).

I've never actually profiled this stuff (and I really don't care to at the moment).


And IPTV solutions are running on octo-processor servers with 32 GB of RAM. I guess.

The goal was probably to come with a solution that doesn't require neither a malloc nor any temporary, even if the temporary is stored in a register (this is why the xor is good here). The goal is not to be optimal in execution time, but to be optimal resource-wise - because a difference of a few nanosecond will not hurt your code, while badly used resources can really hurt - especially in an embedded environment.

Quote:By Sneftel
"The compiler can do better" is one compelling argument. To the compiler, where possible, std::swap means "switch the register allocations", and masses-of-XOR means "masses of XOR". The big thing, though, is pipelining. a^=b unavoidably ties up both a and b for one clock cycle, and then unavoidably keeps a tied up for the next clock cycle. Since the next instruction needs to read back from a, this means that in the simplest possible case, the three instructions are completely serialized, taking six cycles.

Now consider the temp case. The first op, t=a, takes two cycles as well, but as soon as the first cycle is complete, a is no longer tied up, and a=b can start executing. Likewise, after one more cycle, b is no longer tied up, and b=t can start executing. In this same simple pipelined processor, the total is four cycles.

True on the current x86 architecture. However, most embedded platforms are using RISC microprocessors where every instruction takes exactly 4 cycles to execute within a 4-step pipeline (fetch instruction, decode, exec, write-back). Anyway, even on these architectures there are more efficient ways to perform the operation (if performance is needed). Most recent RISC microprocessors have an "exchange" instruction that swap the content of two registers. Most compilers which spit code for these microprocessors have intrisic instructions to use this exchange instruction. So you end up with non-standard C, but that's still C.

Quote:Original post by Trienco
In other words and as someone has said before: if you do anything more complicated than calling reverse(someString) in C++, you didn't understand the task ,-)

And, as someone has said before: if you do anything more than using pure, straight C, you didn't understand the task ,-)

Why do people want to force everyone to use C++ when C is doing the job just right?
If the comment about the code being extremely bad was aimed at me... then yeah, no argument from me there. I really don't like C much if at all and have really reached bugger all proficiency in it even though I've had two University courses on it now.

Quote:Original post by apatriarca
If with inline initialization you mean the initialization at declaration than it works on Visual Studio. Can you post an example of this strange behavior?
In C89 the variables should be declared at the start of the block, C99 have removed this limitation (but Visual Studio don’t support C99). I don’t know if there are compilers with 100% C99 support. It isn’t a very successful standard.


Yeah, Visual Studio's C support seems to be an ugly mess of C89 and 99 with some bits hacked about even more. It gave me a warning for something not being valid C99, I did what it told me to do and then it gave me compiler errors. I don't have my laptop handy right now so I'm writing what I vaguely remember going wrong from memory.

The usual C++ method of declaring loop indices inline doesn't seem to work in C:

for (int x = 0; x < 10; x++) // THIS IS ILLEGAL C :({// Do something}int x = 0;for (x = 0; x < 10; x++) // Happy now{// Do something}


Also, Visual Studio didn't like stuff like this (I don't have any means of testing this right now but I remember doing stuff like this and it didn't work):

void blah(){printf("Foo\n");printf("Bar\n");int x = 0; //BOOM!! This should appear at the very top of the function apparently... C++ allows you to declare wherever but apparently C89/99/WTF Visual Studio is using doesn't}


And, IIRC but as I say I haven't had time to check this, VS didn't like:
char* foo = "bar"; // VS blew up; this compiled fine under gccchar* foo;foo = "bar"; // Happy now, providing char* foo is at the top of the function


I never really took to C at all, but the question was being asked in terms of stripped down hardware like a small IPTV network receiver (not epic servers although those do exist at one point in their setup). I don't know whether it's

a) Me still missing the point of C and not getting how it works (which seems to be radically different to C++ in a few ways; the syntax is very clumsy and I often find things either don't work at all or do work, but don't do what you expect and with little obvious reason for it)
b) VS being picky about ancient legacy code (wouldn't surprise me)
c) both of the above.
Quote:Original post by ukdeveloper
Also, Visual Studio didn't like stuff like this (I don't have any means of testing this right now but I remember doing stuff like this and it didn't work):

*** Source Snippet Removed ***

And, IIRC but as I say I haven't had time to check this, VS didn't like:
*** Source Snippet Removed ***


All your variables must be declared at the beginning of a block. If the compiler complains about directly initializing them, try not to call functions during initialization (ie. try it with a constant expresssion instead of strlen).

Quote:a) Me still missing the point of C and not getting how it works (which seems to be radically different to C++ in a few ways; the syntax is very clumsy and I often find things either don't work at all or do work, but don't do what you expect and with little obvious reason for it)


"Good" old C has plenty of things to look out for. The most obvious is the annoying way you need to use typedefs, because structs/enums are pretty much anonymous.

So (from hazy memory):
struct Bla {};
won't work, instead you need to do
typedef struct {} Bla;
essentially typedef'ing the unnamed struct to Bla. Confusing compared to
struct Bla {} obj;
which in C++ declares the named struct and creates a global instance.
Also, you can't just use
Bla obj;
but need to use
struct Bla obj;

Most limitations might be gone in C99, but I got used to being stuck with the "old" C when using VC++ and thank god never really had to use pure C anyway.

If they require you to use plain C it would be a very good idea to read up on the differences.
f@dzhttp://festini.device-zero.de
Quote:Original post by ukdeveloper

a) Me still missing the point of C and not getting how it works (which seems to be radically different to C++ in a few ways; the syntax is very clumsy and I often find things either don't work at all or do work, but don't do what you expect and with little obvious reason for it)


It's bare bones. WYSIWYG. In C++, writing Foo bar; can expand into millions of lines of code. It is nothing but glorified portable assembly. If you write i++, you get inc eax (and you know it). None of fancy iterators using smart pointers to reference multiple containers through remote persistence....

C has evolved through use, and standard adapted to that (rather than the other way around).

Quote:b) VS being picky about ancient legacy code (wouldn't surprise me)


IIRC VS supports C89 fairly well, but doesn't support recent extensions. At the same time, VS doesn't either claim to, or try, to support C extensively. Its support however is adequate for purposes of C++ and backward interoperability.

Quote:c) both of the above.


C is OS language. It's used for kernels or embedded systems, where it shines as glorified assembly.

It's such a perfect language for the task that it stood the test of time. Even today, C++ cannot escape its legacy.

C++ programmers tend to have issues with C for a very simple reason: C is not C++ without classes.

For a programmer, spending a weekend learning C syntax (it really is kinda that simple) is well spent, so is trying to do some simple things. It's programming without crutches, and may require one to rethink, or at least realize, the true costs of many operations.
Quote:Original post by ukdeveloper
And, IIRC but as I say I haven't had time to check this, VS didn't like:
*** Source Snippet Removed ***

What version of VS do you have? The following compile on my version (VS 2008):
char* foo2 = "bar"; // VS blew up; this compiled fine under gccint main(){	char* foo = "bar"; // VS blew up; this compiled fine under gcc	return 0;}


The other examples you have posted are only valid in C99 and VS, as far as I know, have decided to don’t give support to C99. But the initializations in your last example was also valid in C89 and it should compile on every version of VS.

[Edited by - apatriarca on June 27, 2008 1:55:46 PM]
Quote:Original post by apatriarca
@ Zahlman: Your code don’t compile on my compilers. You have written char[] source but I think the only valid way to declare an array in C is putting the [] after the identifier. So it should be char source[]. I think is just a typo.


Errrrr. Too much time spent in Java I guess :)
Quote:Original post by Trienco
"Good" old C has plenty of things to look out for. The most obvious is the annoying way you need to use typedefs, because structs/enums are pretty much anonymous.

So (from hazy memory):
struct Bla {};
won't work, instead you need to do
typedef struct {} Bla;
essentially typedef'ing the unnamed struct to Bla. Confusing compared to
struct Bla {} obj;
which in C++ declares the named struct and creates a global instance.
Also, you can't just use
Bla obj;
but need to use
struct Bla obj;


You're kind of right.

In C:

struct foo { int bar; };foo f; /* illegal, type foo undefined */struct foo f; /* fine */typedef struct foobar { int bar; } foo;foo f; /* fine */struct foobar f; /* also fine */struct foo f; /* illegal, type struct foo undefined */typedef struct { int bar; } foo; /* works on most compilers, however some old/weird compilers disallow anonymous structs */


Enums and unions work similarly.
Quote:Original post by Zahlman
EDIT: Yeah, I suppose actually moving the pointers used for iteration would be a good idea. And of course someone noticed before I could correct it. That's what you get for writing that much by way of explanation, I guess. X_X


Just out of curiousity, wouldn't it be easier/more readable to use a for loop, instead?
for (; begin < end; ++begin, --end) {    char c = *begin;    *begin = *end;    *end = c;}
Yeah yeah yeah. I wasn't actually thinking it through, OK? And I really hate C, OK? :)

This topic is closed to new replies.

Advertisement