Размер переменной типа void [duplicate]

Вы можете использовать pandas.DataFrame.fillna с опцией method='ffill'. 'ffill' означает «прямое заполнение» и будет распространять последнее действительное наблюдение вперед. Альтернативой является 'bfill', который работает одинаково, но обратный.

import pandas as pd

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
df = df.fillna(method='ffill')

print(df)
#   0  1  2
#0  1  2  3
#1  4  2  3
#2  4  2  9

Для этого также существует функция прямого синонима, pandas.DataFrame.ffill , чтобы сделать вещи проще .

60
задан Peter Mortensen 3 November 2009 в 11:44
поделиться

10 ответов

Тип void не имеет размера; это будет ошибка компиляции. По той же причине вы не можете сделать что-то вроде:

void n;

EDIT. К моему удивлению, выполнение sizeof(void) на самом деле делает компиляцию в GNU C:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 
1

Однако в C ++ это не:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out 
<stdin>: In function 'int main()':
<stdin>:1: error: invalid application of 'sizeof' to a void type
<stdin>:1: error: 'printf' was not declared in this scope
45
ответ дан Jonathan Leffler 21 August 2018 в 03:08
поделиться
  • 1
    Но GCC имеет возможность рассматривать «sizeof (void) == sizeof (char)» ... См. -Wpointer-arith – Jonathan Leffler 3 November 2009 в 10:37
  • 2
    @ Jon это для дураков с начала 80-х годов, которые только начали учиться программированию. Стандарты не получили широкого распространения. – unixman83 16 July 2011 в 15:56
  • 3
    Почему это принятый ответ? – michaelsnowden 6 February 2014 в 09:15
  • 4
    sizeof (void) является нарушением ограничения. Соответствующий компилятор C (который gcc не по умолчанию) должен, по крайней мере, предупреждать об этом, и может (и IMHO) отклонить его. Ссылка: N1570 6.5.3.4p1 (void является неполным типом). Так было со стандартом 1989 года, который ввел void. – Keith Thompson 1 February 2015 в 04:06
  • 5
    @ unixman83: Это не имеет смысла. void не существовало до того, как оно было введено стандартом ANSI C 1989 года, тем же стандартом, который сделал sizeof (void) нарушение ограничения. – Keith Thompson 1 February 2015 в 04:06

sizeof() не может применяться к неполным типам. И void является неполным типом, который не может быть завершен.

5
ответ дан Aleksei Potov 21 August 2018 в 03:08
поделиться

В C, sizeof(void) == 1 в GCC, но это зависит от вашего компилятора.

В C ++ я получаю:

In function 'int main()':
Line 2: error: invalid application of 'sizeof' to a void type
compilation terminated due to -Wfatal-errors.
3
ответ дан Greg Hewgill 21 August 2018 в 03:08
поделиться
  • 1
    Только в GCC sizeof (void) == 1; в стандарте это неопределенное поведение. – Jonathan Leffler 3 November 2009 в 10:38
  • 2
    Обновлено для добавления специального примечания GCC. – Greg Hewgill 3 November 2009 в 10:48
  • 3
    @JonathanLeffler: Это не просто неопределенное поведение. Это нарушение ограничений. N1570 6.5.3.4p1. – Keith Thompson 1 February 2015 в 04:08

Если вы используете GCC, и вы не используете флагов компиляции, которые удаляют специфические расширения для компилятора, тогда sizeof(void) равно 1. GCC имеет нестандартное расширение , которое делает это.

В общем случае void является неполным типом, и вы не можете использовать sizeof для неполных типов.

36
ответ дан hrnt 21 August 2018 в 03:08
поделиться
  • 1
    Опция -Wpointer-arith подразумевается -pedantic. Я всегда использовал -pedantic. :) – Josh Lee 3 November 2009 в 13:13
  • 2
    @jleedev В самом деле, я также использую -патентный, насколько могу. К сожалению, однако, некоторые сторонние заголовки библиотеки делают gcc -pedantic очень грустным :( – hrnt 11 November 2009 в 16:33
  • 3
    +1 Действительно, почему у GCC есть тысячи бесполезных расширений? – user 25 January 2012 в 23:42
  • 4
    @ user142019: потому что они полезны? И помогает получать согласованную бэкэнд-модель с помощью разных языков программирования и аппаратной архитектуры. – kriss 26 November 2014 в 16:00

void не имеет размера. В C и C ++ выражение sizeof (void) недействительно.

В C, цитируя N1570 6.5.3.4, пункт 1:

Оператор sizeof не должен применяться к выражению, имеющему тип функции или неполному типу , к имени в скобках такого типа или выражению, которое обозначает член битового поля.

(N1570 - проект стандарта ISO C 2011 года.)

void является неполным типом. Этот абзац является ограничением , что означает, что любой соответствующий C-компилятор должен диагностировать любое его нарушение. (Диагностическое сообщение может быть предупреждением, не несущественным.)

Стандарт C ++ 11 имеет очень похожую формулировку. Оба выпуска были опубликованы после того, как этот вопрос был задан, но правила восходят к стандарту ANSI C 1989 года и самым ранним стандартам C ++. На самом деле правило, что void является неполным типом, к которому sizeof не может применяться, возвращается точно так же, как введение void в язык.

gcc имеет extension , который рассматривает sizeof (void) как 1. gcc по умолчанию не является совместимым компилятором C, поэтому в режиме по умолчанию он не предупреждает о sizeof (void). Расширения, подобные этому, разрешены даже для полностью совместимых компиляторов C, но диагностика по-прежнему требуется.

6
ответ дан Keith Thompson 21 August 2018 в 03:08
поделиться
  • 1
    Я предполагаю, что они допустили sizeof(void) == 1 для согласованности с арифметикой указателя на указателе void, что также является расширением gcc . Ссылаясь на их документацию: A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.. Но все же диагностическое сообщение должно присутствовать по умолчанию для C, как это требует Стандарт. – Grzegorz Szpetkowski 21 February 2015 в 12:51
  • 2
    @GrzegorzSzpetkowski: (Ответ через пару лет.) Да, стандарт требует диагностики, но gcc по умолчанию не является совместимым компилятором C. Логически, стандарт C не предъявляет никаких требований к реализациям, которые не претендуют на то, чтобы соответствовать ему. gcc можно сделать (почти) соответствующим параметрам командной строки, например -std=c11 -pedantic. С такими параметрами он выдает необходимую диагностику. – Keith Thompson 7 September 2017 в 23:59

Хотя void может стоять на месте для типа, он фактически не может удерживать значение. Поэтому он не имеет размера в памяти. Получение размера void не определено.

Указатель void - это просто языковая конструкция, означающая указатель на память untyped .

15
ответ дан Konrad Rudolph 21 August 2018 в 03:08
поделиться
  • 1
    И что ? Должна ли какая-либо пустая структура не потреблять никакого размера в памяти, и это должно быть проблемой. Ну, на самом деле, мне интересно, если пустые структуры действительно используют 0 байтов в C ++ (как это верно в C) выглядит как sizeof returns 1 для них. – kriss 21 March 2013 в 11:22
  • 2
    @kriss Я не уверен, что вы говорите, но, как вы заметили себя, пустые структуры do занимают память по причинам идентичности объекта. – Konrad Rudolph 21 March 2013 в 11:35
  • 3
    действительно, но это было неверно в C и использование памяти для пустых объектов чувствует зло. – kriss 21 March 2013 в 14:39

Большинство компиляторов C ++ выбрали для повышения компиляции при попытке получить sizeof(void).

При компиляции C gcc не соответствует и решил определить sizeof(void) как 1. Это может показаться странным, но имеет логическое обоснование. Когда вы выполняете арифметику указателя, добавляя или удаляя одну единицу, это означает добавление или удаление объекта, указывающего на размер. Таким образом, определение sizeof(void) как 1 помогает определить void* как указатель на байт (нетипизированный адрес памяти). В противном случае у вас было бы удивительное поведение, используя арифметику указателя, такую ​​как p+1 == p when p void*. Такая арифметика указателя на указателях void не допускается в c ++, но отлично работает при компиляции C с gcc.

. Рекомендуемым стандартным способом было бы использовать char* для этой цели (указатель на байт).

Еще одно подобное различие между C и C ++ при использовании sizeof возникает, когда вы определили пустую структуру типа:

struct Empty {
} empty;

Использование gcc в качестве моего компилятора C sizeof(empty) возвращает 0. Используя g ++ тот же код вернет 1.

Я не уверен, что называет состояние как стандартов C, так и C ++ в этой точке, но я считаю, что определение размера некоторых пустых структур / объектов помогает в управлении ссылками, чтобы избежать этих двух ссылки на разные последовательные объекты, первый из которых пуст, получает тот же адрес. Если ссылка реализована с использованием скрытых указателей, как это часто делается, обеспечение того, что другой адрес поможет их сравнить.

Но это просто избегает неожиданного поведения (сравнение ссылок на столбик) путем введения другого (пустые объекты, даже POD потребляют не менее 1 байт памяти).

-1
ответ дан kriss 21 August 2018 в 03:08
поделиться
  • 1
    «C вместо этого выбрал sizeof (void) как 1.» - Нет, это неправильно. sizeof(void) не определен в C, как в C ++. GCC просто не соответствует в этой точке, а указательная арифметика на указателях void просто не определена - void* p; p++; является недопустимым. Даже GCC даст вам предупреждение при компиляции с флагом -pedantic. И вы также ошибаетесь в отношении поведения GCC по умолчанию для C ++: по умолчанию это рассматривается как ошибка . – Konrad Rudolph 21 March 2013 в 11:37
  • 2
    @Konrad: да, я совершенно уверен, что это было неверно с более старой версией gcc, но современные, как вы говорите. – kriss 21 March 2013 в 14:40
  • 3
    По крайней мере, в C пустым struct определением является синтаксическая ошибка; Поддержка gcc - это расширение. Они могут быть действительными в C ++; Я не уверен. – Keith Thompson 1 February 2015 в 04:20

Взятие размера void является расширением GCC .

9
ответ дан pmg 21 August 2018 в 03:08
поделиться

Во вторую часть вопроса: Обратите внимание, что sizeof (void *)! = sizeof (void). В 32-битной дуге sizeof (void *) составляет 4 байта, поэтому p ++ будет установлен соответствующим образом. Величина, на которую увеличивается указатель, зависит от данных, на которые он указывает. Таким образом, он будет увеличен на 1 байт.

0
ответ дан user 21 August 2018 в 03:08
поделиться
  • 1
    поэтому p указывал на 1 байтовые данные, так как sizeof (void) дает 1, поэтому p ++ означает, что p будет увеличиваться на 1, а не 4? – Lakshmi 3 November 2009 в 10:58
  • 2
    Количество, на которое увеличивается указатель, зависит от данных, на которые он указывает. Так да. – user 3 November 2009 в 11:32
  • 3
    p имеет тип void * (void pointer), а не void. Таким образом, он будет увеличиваться на размер типа void * (обычно это 4 в 32-битных системах). – Technowise 3 November 2009 в 11:59
  • 4
    @Technowise: нет. Любой указатель типа T* увеличивается на sizeof(T) not sizeof(T*), что почти всегда будет одинаковым, кроме возможно для указателей функций), когда оно увеличивается. Исключением является, конечно, void (и снова исключение - это когда включены расширения GCC). – Konrad Rudolph 3 November 2009 в 18:48
  • 5
    @Amit: Как вы пришли к выводу, что размер указателя a void* указывает на 1 байт? sizeof (void) является нарушением ограничения. (Расширение gcc рассматривает его как 1.) – Keith Thompson 1 February 2015 в 04:09

, в то время как sizeof (void), возможно, не имеет смысла сам по себе, важно, когда вы делаете какую-либо математику указателя.

например.

 void *p;
 while(...)
      p++;

Если sizeof (void ) считается 1, тогда это сработает. Если sizeof (void) считается 0, вы попадаете в бесконечный цикл.

-1
ответ дан user906752 21 August 2018 в 03:08
поделиться
  • 1
    Пример фрагмента кода является незаконным в C и C ++. Некоторые компиляторы разрешают это в любом случае. – James Roth 13 September 2013 в 18:05
  • 2
    Нет, это совсем не важно (хотя авторы gcc явно думали, что это так). Если вы хотите выполнить арифметику указателя на указателях байтов, используйте unsigned char*. – Keith Thompson 1 February 2015 в 04:07
Другие вопросы по тегам:

Похожие вопросы: