+1  A: 
  1. If it's a char[] and not a char *, sizeof() will give you the array size (which is strlen() + 1 for nul-terminated strings). If you need to work extensively with strings (especially ones that may have the '\0' character in them and/or may not be nul-terminated) you should consider using a string library. It will make your life much easier.
  2. Whatever you want. I personally never use capital letters in identifiers, because I think MixedCaseIdentifiers are ugly. There is no convention for naming identifiers, only conventions that some people like. Use whatever looks best to you (and your team).
  3. You can do this:

    struct s {
        int         bar1;
        char*       bar2;
        callback    bar3;
    };
    struct s *foo = NULL;
    static struct s default = { 0, "Hello, world!", myFunc };
    foo = malloc(sizeof *foo);
    *foo = s;
    

    My standards-fu is failing me, so I'm not sure why this works (or even if it does absolutely) but I believe it does. If it doesn't work, you just need to make an init function that sets all the fields to their default values.

  4. Consistency. When assigning an address to a pointer, it's normally necessary, i.e. int i = 5, *j = &i; so even though it's not strictly necessary for function pointers, some people like to do it so that all pointer assignments look the same. It's just aesthetics.

However, in the future, most of these questions are unrelated to each other. You shouldn't group four unrelated questions into one giant monster question, but instead ask them separately. It'll make you take more time for each one, and each will come out more coherently so we'll be able to give you better answers (and you'll learn more).

Chris Lutz
OK, thank you, I'm new here so I don't know all the unwritten rules. I thought that serially opening too many questions would be selfish or something.
Dor
@Chris Lutz - That code doesn't compile for me. I'm using g++ (the version bundled with cygwin, not sure on the exact version number). I think you need a cast on malloc, feel free to correct me if I'm wrong.
dcp
@dcp: Why are you using g++ (and not gcc) on C code? `malloc` doesn't need a cast in straight C.
jamesdlin
The "casting `malloc()`" debate can go on and on, but in summary: If you need people to compile it with a C++ compiler, you have no choice and must cast. If you don't need this, you can cast if you want, but if you don't a) you will be warned if you forgot to include `<stdlib.h>` (with a cast it will silently fail, as `malloc()` has been given an implicit signature) and b) if the type changes later (say, from `char *` to `wchar_t *`) you don't need to go back and change all your casts (this is the same reason to use `sizeof *foo` instead of `sizeof(struct foo)`). The second is most compelling.
Chris Lutz
@Chris Lutz - nice explanation, thanks very much.
dcp
Note that `sizeof` will give the size of the array in *bytes*, not the number of elements. For arrays of `char`, this is the same thing, but for other types it is not. For an array of type T, where T is not char, the number of *elements* is given by `sizeof arr / sizeof arr[0]`.
John Bode
@John Bode - This is true. Ideally there would be a macro `#define ARR_LEN(x) (sizeof(x) / sizeof((x)[0]))` to do this for us. (Ideally we could use templates in C++ and prevent people from abusing our macro with pointers but pure C has it's advantages so I won't be one of those "why not use C++?" people.)
Chris Lutz
+1  A: 
  1. sizeof is good enough for this

  2. Matter of taste. I don't use capitals in identifiers at all (unless they are global constants)

  3. You can do this:

    struct foo {
        int   a;
        char  *b;
    } bar;
    
    
    bar = (struct foo){0, "Hello"};
    
  4. To make it explicit, although it is not necessary, if myFunc is a function.

qrdl
+1  A: 

If you want to copy values from one struct to another, you can do this:

typedef struct {
    int         bar1;
    char*       bar2;
    int (*callback)(int);
} mystruct;

char str[] = "Hello \x45\x10\x00 World!";

int main() { 
  mystruct* foo = (mystruct*)malloc(sizeof(mystruct));
  mystruct* foo2 = (mystruct*)malloc(sizeof(mystruct));
  foo->bar1 = 10;
  foo->bar2 = "hi";

  printf("foo->bar1 = %d, foo->bar2 = %s\n",foo->bar1,foo->bar2);

  memcpy(foo2,foo,sizeof(*foo));

  printf("foo2->bar1 = %d, foo2->bar2 = %s\n",foo2->bar1,foo2->bar2);

  free(foo);
  free(foo2);
  return 0;
}

Output:

---------- Capture Output ----------
> "c:\windows\system32\cmd.exe" /c c:\temp\temp.exe
foo->bar1 = 10, foo->bar2 = hi
foo2->bar1 = 10, foo2->bar2 = hi

> Terminated with exit code 0.
dcp
A: 

2 I use the c# recommendations

If 2 initials then all caps, otherwize only initial cap. Examples

DSPointer, FtpServer, getHDSeekTime, sendSmtpMessage

pm100
+1  A: 
  1. In general, the number of elements in an array is given by the expression sizeof arr / sizeof arr[0] (or sizeof arr / sizeof *arr). The sizeof operator returns the size of the array in bytes, not the number of elements, so you must divide the number of bytes in the array by the number of bytes in an individual element. However, since sizeof char == 1 by definition, you can get the number of elements in a char array with just sizeof arr. Note that the expression arr must be an array type, not a pointer type (for example, if arr was passed as a function parameter typed T arr[], then it's a pointer type, and sizeof will give you the number of bytes in the pointer, not the array itself).

  2. There a number of conventions, none of which are really better than the others. Which convention you pick doesn't matter as long as you use it consistently.

  3. C89 doesn't support compound literals like that. C99 does, and it should look something like *foo = (struct s) {0, "Hello, World", myfunc}; (assuming you add a tag s to your struct definition). However, I'm not that familiar with C99 features, so don't take that as gospel.

  4. Habit. In practice it does nothing (a function designator is implicitly converted to a pointer to a function under the usual conversion rules anyway).

John Bode