Размер предопределенного / назначенного символа [], соглашения об именах, простое копирование структуры и выбор адреса функции с помощью амперсанда - PullRequest
1 голос
/ 13 января 2010
  1. Как найти размер предопределенной переменной char [], содержащей строку? Должен ли sizeof быть достаточно? Я не хочу использовать strlen (), поскольку в строке может встречаться символ '\ 0', и по причинам оптимизации. Например: char str[] = "Hello \x45\x10\x00 World!";

  2. Что вы делаете, когда в идентификаторе есть инициалы? Например. GetURLParameters (). Я думал о добавлении подчеркивания: GetURL_Parameters (). Каково соглашение для этой ситуации?

  3. Как я могу легко скопировать значения в поля структуры, на которую указывает переменная / указатель? Например, я хотел бы сделать что-то похожее на:

    struct {
    int         bar1;
    char*       bar2;
    callback    bar3;
    } *foo = NULL;
    foo = malloc(sizeof *foo);
    *foo = { 0, "Hello World!", myFunc };   // This is wrong
    
  4. Почему программисты иногда используют амперсанд для присвоения адреса функции указателю функции? Например:

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

    (Извините, но я не могу отредактировать свое сообщение. Оно выглядит по-разному, когда я редактирую и когда вам показывают)

Ответы [ 5 ]

1 голос
/ 13 января 2010
  1. Как правило, количество элементов в массиве определяется выражением sizeof arr / sizeof arr[0] (или sizeof arr / sizeof *arr).Оператор sizeof возвращает размер массива в байт , а не количество элементов, поэтому необходимо разделить количество байтов в массиве на количество байтов в отдельном элементе.Однако, так как sizeof char == 1 по определению, вы можете получить количество элементов в массиве char с помощью sizeof arr.Обратите внимание, что выражение arr должно иметь тип array , а не тип указателя (например, если arr был передан как параметр функции, набранный T arr[], то это тип указателя, и sizeof даст вам количество байтов в указателе, а не сам массив).

  2. Существует целый ряд соглашений, ни один из которых не лучше других.Какое соглашение вы выберете, не имеет значения, если вы используете его последовательно.

  3. C89 не поддерживает составные литералы, подобные этому.C99 делает, и это должно выглядеть примерно так: *foo = (struct s) {0, "Hello, World", myfunc}; (при условии, что вы добавите тег s в определение структуры).Однако я не очень знаком с функциями C99, поэтому не воспринимайте это как Евангелие.

  4. Привычка.На практике это ничего не делает (в любом случае обозначение функции неявно преобразуется в указатель на функцию по обычным правилам преобразования).

1 голос
/ 13 января 2010
  1. sizeof достаточно для этого

  2. Дело вкуса. Я вообще не использую заглавные буквы в идентификаторах (если они не являются глобальными константами)

  3. Вы можете сделать это:

    struct foo {
        int   a;
        char  *b;
    } bar;
    
    bar = (struct foo){0, "Hello"};
    
  4. Чтобы сделать это явным, хотя это и необязательно, если myFunc является функцией.

1 голос
/ 13 января 2010

Если вы хотите скопировать значения из одной структуры в другую, вы можете сделать это:

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;
}

Выход:

---------- 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 голос
/ 13 января 2010
  1. Если это char[], а не char *, sizeof() даст вам размер массива (который strlen() + 1 для строк с нулевым символом в конце). Если вам нужно много работать со строками (особенно те, которые могут содержать символ '\0' в них и / или могут не заканчиваться нулем), вам следует рассмотреть возможность использования библиотеки строк. Это сделает вашу жизнь намного проще.
  2. Как хочешь. Лично я никогда не использую заглавные буквы в идентификаторах, потому что думаю, что MixedCaseIdentifiers безобразны. Для именования идентификаторов нет соглашения, только соглашения, которые нравятся некоторым людям. Используйте то, что вам больше всего нравится (и вашей команде).
  3. Вы можете сделать это:

    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;
    

    Мои стандарты-фу меня подводят, поэтому я не уверен, почему это работает (или даже если оно работает абсолютно), но я верю, что это работает. Если это не работает, вам просто нужно сделать функцию init, которая устанавливает для всех полей значения по умолчанию.

  4. Последовательность. При назначении адреса указателю это обычно необходимо, т. Е. int i = 5, *j = &i;, поэтому, хотя это не является строго необходимым для указателей на функции, некоторым людям нравится делать это так, чтобы все назначения указателей выглядели одинаково. Это просто эстетика.

Однако в будущем большинство этих вопросов не связаны друг с другом. Вы не должны группировать четыре несвязанных вопроса в один гигантский вопрос монстра, а вместо этого задавать их отдельно. Это заставит вас уделять больше времени каждому, и каждый будет выходить более согласованно, поэтому мы сможем дать вам лучшие ответы (и вы узнаете больше).

0 голосов
/ 13 января 2010

2 Я использую рекомендации C #

Если 2 инициала, то все заглавные буквы, в противном случае - только заглавные буквы. Примеры

DSPointer, FtpServer, getHDSeekTime, sendSmtpMessage

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...