Showing posts with label c. Show all posts
Showing posts with label c. Show all posts

Wednesday, September 16, 2009

sizeof(char)

It does not seem to be common knowledge what sizeof(char) returns and why. So I will try to cover that.

If you're new to C, you may be assuming that a char is always 8 bits, and that sizeof(char) is thus always 1. It is correct that sizeof(1) is always equal to 1, but it's for another reason, and a char may be bigger than 8 bits.

So, thus if you're an intermediate C programmer, you may know this, and for example use malloc((n+1) * sizeof(char)). The multiplication is redundant, however, because as I stated above, sizeof(char) is always equal to 1. Why?

The reason is that sizeof() returns sizes on units of the size of char; that is, sizeof(char) must be equal to 1 as, well, a char is as big as a char. This also means that the sizes of all datatypes (with potential padding) must be in multiples of CHAR_BIT (a macro which expands to the number of bits in a char).

And as you might have guessed, the sizes passed to malloc et al are not in multiples of 8 bits, they are in units of sizeof(char).

In the standard, a char is defined to be the same size as a byte. This means that a byte can be bigger than 8 bits. There are examples of C compilers which define a char, and thus a byte, as 9, 16, 32 or 36 bits.

Sunday, July 26, 2009

Local "DOS" against the NVidia Linux driver

Because of a bug, I found out that looping on glClear causes very painful results with the NVidia Linux driver. It makes the desktop unusable, updating only every 2 seconds, and no events will reach any program. Only way to get out of it is to switch to a tty, then events seem to be transmitted, and the program will be exited. X crashed once when I switched to a tty, tho. Try out on your own risk.

EDIT: Warning: Seems that I didn't fix the bug in the program, so I got into the same situation again (however, my program runs a few gl statements in between every glClear) and the machine became so unresponsive that I couldn't even switch to a tty (had no second computer to ssh in with, that would likely have solved it). I repeat, run it at your own risk.

Here's a test-case:
#include <sdl.h>
#include <gl.h>

int main(int argc, char *argv[])
{
SDL_Surface *screen;
int i = 0;

SDL_Init(SDL_INIT_VIDEO);

screen = SDL_SetVideoMode( 640, 480, 0, SDL_OPENGL | SDL_GL_DOUBLEBUFFER );

glMatrixMode(GL_MODELVIEW);

while (1)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
SDL_Quit();

return 0;
}

Note that I am running a rather old version of the NVidia Linux driver, 173.14.09, they could very well have fixed this in newer versions.

Sunday, June 28, 2009

GDB 7 will bring major improvements

According to GDB and Debian Developer Daniel Jacobowitz, GDB 7 will bring major improvements:

Improvements mentioned are:
  • Support for understanding inlined functions -- that is, you will actually be able to step in, through and out of them, and get backtraces that include inlined functions!
  • Support for pretty-printing STL containers etc!
  • Python scripting.
So it appears that this release will be a great one. It's slated for this fall.

Oh, and on another sidenote -- I must promote cgdb again, it simplifies debugging with gdb a lot. It will also benefit from these improvements. It could be that it could need a feature or two to make these new features easier to use (python scripting, perhaps?). Sadly, upstream of cgdb appears to be quite dead; no release since 2007.

Function returning function pointer: funny syntax

Take a look at this:

void (*f())(void*);

At a first glance, it may look like some kind of special function that returns void and takes a void*. That's totally wrong. It's actually a function that takes zero arguments, and returns function pointer, a void (*)(void*) -- that is, a pointer to a function pointer that returns void and takes a void*. The syntax actually makes a little sense if you consider the syntax for defining a variable containing such a function:

void (*f)(void*);

Typedefs of function pointers are weird too:

typedef void (*ptrFunc)(void*);

But I can't help to think that the following syntax would be much clearer:

void (*)(void*) f(); // invented syntax
void (*)(void*) f;
typedef void (*)(void*) ptrFunc;

These would make a lot more sense than the current function pointer syntax in C/C++, and would 'logically match' other declarations -- [return] type followed by an identifier (followed by argument list if it is a function), instead of mixing [return] type, identifier and argument list into one big mess.
It may be that the invented syntax is harder to parse -- I have thought a while on this, but haven't come to a reliable conclusion. The syntax may just be a historical artifact.

In any case, this odd syntax must be the reason why you usually define typedefs for function pointers, as done above. Then we can use the following syntax:

ptrFunc f();
ptrFunc f;

Much cleaner and understandable -- the obvious drawback is: what's a ptrFunc? You'll have to find the typedef to know. But I think that's worth it.