2013-03-17 3 views
0

Я немного смущен тем, что передать в качестве первого параметра memset, когда вам нужно установить элементы статического массива. Я искал, но я не мог найти ответы на некоторые конкретные вопросы, которые у меня есть.memset on static array

Если я массив объявлен как:

char arr[10]; 

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

memset(arr, 0, 10); 
memset(&arr, 0, 10); 

Мои конкретные вопросы:

1- Почему они оказывают такое же влияние на arr?

2- Что отличает эти звонки?

3 Какой из них будет считаться правильным?

Спасибо!

+5

Правильный способ установить их все в ноль: 'char arr [10] = {};' – ipc

ответ

4

Срок хранения не имеет к этому никакого отношения; массив - это массив. Это выражение:

&arr 

производит char (*)[10], то есть, указатель на массив char с 10 элементами. Однако, когда arr передается функции следующим образом:

memset(arr, 0, 10); 

он деградирует на указатель на первый элемент, т.е. char*. Это не одно и то же.«Правильный» (идиоматичен) вызов:

memset(arr, 0, 10); 

Тем не менее, в этом случае они оба преобразуются в void*, когда передается memset и интерпретируется в качестве функции unsigned char*. Поскольку оба они указывают на одно и то же место, он дает тот же результат.

Тем не менее, важно понимать, что, при работе с истинными соответствующими типами (т.е. не void*), указатель на массив является не такими же, как указатель на первый элемент массива.

Например, приращение char (*)[10] будет увеличивать указатель sizeof(char[10]) байтов, а приращение char* будет увеличивать только один байт.

+0

Ах! имеет смысл, спасибо! – santi

+1

Одна коррекция: 'и интерпретируется в функции как char *' должна быть изменена на 'unsigned char *'. –

+0

@JesseGood: Да, хороший звонок. –

0

1- Почему они оказывают такое же влияние на arr?

Оба они содержат то же значение, которое является адресом начала массива.

2- Что отличает эти звонки?

arr распадается на указатель на символ, т.е. char* (это преобразование происходит, когда вы передаете имя массива в функцию) и &arr является указателем на массив полукокса, т.е. char (*)[].

3 Какой из них будет считаться правильным?

Я бы использовал arr. memset принимает void*, который является причиной того, что оба работают.

Также обратите внимание, что char arr[10] = {}; может использоваться для нулевого инициализации массива.

+2

Осторожно - 'arr' является ** не ** указателем на символ, но он может затухать до одного. –

+0

@DrewDormann: Спасибо, трудно быть точным, когда вы печатаете быстро (измененная формулировка). –

2

Почему они оказывают такое же влияние на arr? В чем разница между этими вызовами?

Поскольку адрес массива совпадает с адресом его первого элемента (массивы распадаются на указатели на их первый элемент при передаче функции), просто они имеют другой тип. arr имеет тип char[10], который распадается на char * при передаче функции. Напротив, &arr имеет тип char (*)[10], который не изменяется при передаче в качестве аргумента функции.

Какой из них считается правильным?

Пока функция не ожидает определенного типа, i. е. он принимает void *, любой из них хорош. Если вызываемая функция, однако, ожидает, что любой из типов будет указан, то другой не должен использоваться, так как тогда ваша программа будет искажена и вызовет неопределенное поведение.

+0

Не лучше ли использовать 'memset (arr, 0, 10);'? Он остается действительным, если декларация массива по какой-либо причине изменяется на 'char * arr = new char [10]'. – user502144

+1

@ user502144 Мы не говорим о случае «когда оно меняется». Или, точнее, я упомянул в последней части, когда они действительны. – 2013-03-17 20:47:28