OSX에서 사용되는 x86_64의 호출 규칙을 연구 중이며 the System V x86-64 ABI standard에서 "집계 및 공용체"섹션을 읽었습니다. 그것은 배열을 언급하고 나는 고정 된 길이의 C 배열과 같다고 생각했다. int[5]
.어떤 종류의 C11 데이터 유형이 AMD64 ABI에 따른 배열입니까
"3.2.3 매개 변수 전달"으로 이동하여 배열을 전달하는 방법에 대해 읽었고 정확히 이해하면 uint8_t[3]
과 같은 것이 규칙 1에 지정된 4 개의 8 바이트 제한보다 작기 때문에 레지스터에 전달해야합니다 골재 유형 분류 (18 페이지 하단).
컴파일 한 후 대신 포인터로 전달되는 것을 볼 수 있습니다. (OSX 10.11.6의 Xcode 7.3.1에서 clang-703.0.31로 컴파일 중입니다.) 다음과 같이
내가 컴파일 사용 된 예제 소스는 다음과 같습니다
#include <stdio.h>
#define type char
extern void doit(const type[3]);
extern void doitt(const type[5]);
extern void doittt(const type[16]);
extern void doitttt(const type[32]);
extern void doittttt(const type[40]);
int main(int argc, const char *argv[]) {
const char a[3] = { 1, 2, 3 };
const char b[5] = { 1, 2, 3, 4, 5 };
const char c[16] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 1, 1, 1, 1 };
const char d[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 1, 1, 1, 1 };
const char e[40] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
doit(a);
doitt(b);
doittt(c);
doitttt(d);
doittttt(e);
}
나는 파일에 a.c
이름 컴파일하려면 다음 명령을 사용하는 것이 덤프 : clang -c a.c -o a.o
.
a.o:
(__TEXT,__text) section
_main:
0000000000000000 pushq %rbp
0000000000000001 movq %rsp, %rbp
0000000000000004 subq $0x10, %rsp
0000000000000008 leaq _main.a(%rip), %rax
000000000000000f movl %edi, -0x4(%rbp)
0000000000000012 movq %rsi, -0x10(%rbp)
0000000000000016 movq %rax, %rdi
0000000000000019 callq _doit
000000000000001e leaq _main.b(%rip), %rdi
0000000000000025 callq _doitt
000000000000002a leaq _main.c(%rip), %rdi
0000000000000031 callq _doittt
0000000000000036 leaq _main.d(%rip), %rdi
000000000000003d callq _doitttt
0000000000000042 leaq _main.e(%rip), %rdi
0000000000000049 callq _doittttt
000000000000004e xorl %eax, %eax
0000000000000050 addq $0x10, %rsp
0000000000000054 popq %rbp
0000000000000055 retq
또는 동등하게, 여기가 Godbolt compiler explorer with clang3.7에 리눅스를 대상으로 같은 ABI를 사용 : 나는 (otool -tV a.o
을 실행하여) 생성 된 어셈블리를 분석하고 다음과 같은 출력을 얻을 수 otool 사용합니다.
누군가 C11의 데이터 형식이 배열에 적용될 수 있는지 궁금합니다. (clang은 C11을 사용하는 것으로 기본 설정되어 있습니다 (C99 인라인 기능 아래에 blurb here 참조).
또한 ARM standard에도 어레이 집계 유형이 지정되어 있어도 ARM과 비슷한 조사를 통해 유사한 결과가 나타났습니다.
또한 고정 길이 배열을 포인터로 처리하도록 지정된 일부 표준이 있습니까? 함수 C에서 인수 및 단지 여러 가지 다른 상황에서 같은 포인터로 C++ 항상 붕괴 등
@PeterCordes : 배열은 모든 컨텍스트가 아닌 대부분의 포인터로 붕괴됩니다. 더 중요한 것은 C는 배열 타입의 매개 변수를 허용하지 않는다는 것입니다. void func (int param []);과 같은 선언에서,'param'의 타입은'int []'에서'int *'로 ** 조정 **됩니다. (이는 배열 표현식을 포인터로 암시 적으로 변환하도록 지정하는 규칙과 다릅니다.) –
@PeterCordes 따라서 x86_64/arm 표준에 정의 된대로 배열로 간주되는 c11 또는 c99에는 데이터 유형이 없습니까? – DanZimm
@KeithThompson C가 배열 형식의 매개 변수를 허용하지 않는다는 사실에 대한 참조가 있습니까? 나는 더 많이 읽고 싶다! – DanZimm