开发者

Size of predefined/assigned char[], naming conventions, easily copying a struct and fetching function address with ampersand

  1. How to find the size of a predefined char[] variable that holds a string? Should sizeof be enough? I don't want to use strlen() since a '\0' character may occur in the string, and for optimization reasons. E.g.: char str[] = "Hello \x45\x10\x00 World!";

  2. What do you do when there're initials in the identifier? E.g. GetURLParameters(). I thought of adding an underscore: GetURL_Parameters(). What is the convention for this situation?

  3. How can I easily copy values 开发者_C百科to the fields of a struct that is pointed by a variable/pointer? For example, I would like to do something similar to:

    struct {
    int         bar1;
    char*       bar2;
    callback    bar3;
    } *foo = NULL;
    foo = malloc(sizeof *foo);
    *foo = { 0, "Hello World!", myFunc };   // This is wrong
    
  4. Why programmers sometimes use an ampersand to assign an address of a function to a function pointer? E.g.:

    void (*callback)(void);
    callback = &myFunc;

    (Sorry, but I can't edit well my post. It looks different when I edit, and when it's shown to you)


  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).


  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.


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.


  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).


2 I use the c# recommendations

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

DSPointer, FtpServer, getHDSeekTime, sendSmtpMessage

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜