LINUX.ORG.RU

слегка припух с крестов

 


1

1

Только что слегка припух с крестов, внезапно выяснил что следующая конструкция выкидывает ошибку

unsigned count = block->size();
State lastState[count] = { STATE_START };

мол компилятор изначально хз что есть count, а массив переменной длины это нельзя. про переменную длину не спорю, но это ж блин соседние строки одного блока, где тут переменная длина? объявление count как const не помогает

отвечу всем и сразу - я понимаю что именно может не нравится компилятору, я просто мягко говоря не ожидал такого поведения. размер массива в рантайме вроде как почти во всех языках можно задавать. ну, да, там уже правда не массив, а обычно ссылка на него, иначе размер фрейма хз какой. но никогда не думал что в С это морозилось аж до С99

Перемещено Klymedy из talks

★★★★★

Последнее исправление: upcFrost (всего исправлений: 1)

count неизвестна во время компиляции, так что в мире C/C++ это переменная длина. Попробуй объявить count как constexpr либо включить гнутые расширения.

hateyoufeel ★★★★★
()

про переменную длину не спорю, но это ж блин соседние строки одного блока, где тут переменная длина?

Перестрелка полушарий как она есть.

thesis ★★★★★
()

про переменную длину не спорю, но это ж блин соседние строки одного блока, где тут переменная длина

И что, компилятор откуда знает что _во_время_выполнения_ вернет block? Хотя опять же, GNU-расширения это позволяют, другие ЯП некоторые тоже позволяют.

I-Love-Microsoft ★★★★★
()

А что тебя удивило? По классике, стекфрейм фиксированного размера. Хотя частично на это уже забили, но пока не в крестах.

anonymous
()

Я тут слегка припух с генерируемого кода. Берём простенький пример с VLA:

int func(int n) {
  int vals[n];
  vals[n-1] = 9;
  return 1;
}
собираем его:
gcc -g -O0 -c q.c

Смотрим код:

$ LANG=C objdump -S q.o

q.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <func>:
int func(int n) {
   0:	55                   	push   %rbp
   1:	48 89 e5             	mov    %rsp,%rbp
   4:	48 83 ec 20          	sub    $0x20,%rsp
   8:	89 7d ec             	mov    %edi,-0x14(%rbp)
   b:	48 89 e0             	mov    %rsp,%rax
   e:	48 89 c1             	mov    %rax,%rcx
  int vals[n];
  11:	8b 45 ec             	mov    -0x14(%rbp),%eax
  14:	48 63 d0             	movslq %eax,%rdx
  17:	48 83 ea 01          	sub    $0x1,%rdx
  1b:	48 89 55 f8          	mov    %rdx,-0x8(%rbp)
  1f:	48 63 d0             	movslq %eax,%rdx
  22:	49 89 d2             	mov    %rdx,%r10
  25:	41 bb 00 00 00 00    	mov    $0x0,%r11d
  2b:	48 63 d0             	movslq %eax,%rdx
  2e:	49 89 d0             	mov    %rdx,%r8
  31:	41 b9 00 00 00 00    	mov    $0x0,%r9d
  37:	48 98                	cltq   
  39:	48 c1 e0 02          	shl    $0x2,%rax
  3d:	48 8d 50 03          	lea    0x3(%rax),%rdx
  41:	b8 10 00 00 00       	mov    $0x10,%eax
  46:	48 83 e8 01          	sub    $0x1,%rax
  4a:	48 01 d0             	add    %rdx,%rax
  4d:	be 10 00 00 00       	mov    $0x10,%esi
  52:	ba 00 00 00 00       	mov    $0x0,%edx
  57:	48 f7 f6             	div    %rsi
  5a:	48 6b c0 10          	imul   $0x10,%rax,%rax
  5e:	48 29 c4             	sub    %rax,%rsp
  61:	48 89 e0             	mov    %rsp,%rax
  64:	48 83 c0 03          	add    $0x3,%rax
  68:	48 c1 e8 02          	shr    $0x2,%rax
  6c:	48 c1 e0 02          	shl    $0x2,%rax
  70:	48 89 45 f0          	mov    %rax,-0x10(%rbp)
  vals[n-1] = 9;
  74:	8b 45 ec             	mov    -0x14(%rbp),%eax
  77:	8d 50 ff             	lea    -0x1(%rax),%edx
  7a:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
  7e:	48 63 d2             	movslq %edx,%rdx
  81:	c7 04 90 09 00 00 00 	movl   $0x9,(%rax,%rdx,4)
  return 1;
  88:	b8 01 00 00 00       	mov    $0x1,%eax
  8d:	48 89 cc             	mov    %rcx,%rsp
}
  90:	c9                   	leaveq 
  91:	c3                   	retq   

Э-э-э... шта?

i-rinat ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

причем ведь это в стек идет?

Это вроде как зависит от реализации, так что никто ничего не может гарантировать.

hateyoufeel ★★★★★
()

Ну так константная переменная - не значит константа в compile-time в общем случае, вот и не разрешено (кроме глобальных констант, емнип). constexpr можно.

anonymous
()
Ответ на: комментарий от monk

Похоже на выравнивание

делением?

upcFrost ★★★★★
() автор топика
Ответ на: комментарий от i-rinat

Типичный неоптимизированный код. Поделили на 16, умножили на 16. Выравнивание стекфрейма же. Вроде по ABI требуется (что, в свою очередь, требуется для всяких SIMD). Что не так?

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)

где тут переменная длина?

block->size()

Если она известна на этапе компиляции (например, если block — это std::array<>), то и пиши constexpr.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от i-rinat
#include <stdio.h>

int func(int n) {
    int vals[n];
    vals[n-1] = 9;
    printf("%i\n", sizeof(vals));
    return 1;
}

int main() {
    func(10);
    func(20);
}
anonymous
()
Ответ на: комментарий от i-rinat

Я привык видеть «and» для такого.

Это уже оптимизация.

monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.