2013-09-26 4 views
14

에서 문자열의 주소를 인쇄하는 것입니다 (나는 C를 배우고 이것은 어리석은 질문 일 수 있습니다. 죄송합니다) How to declare strings in C으로 당과 대부분의그것이 유효 내가 ...이 개 질문이 C

  • 책, 그들은 항상

    char p2[] = "String"; 
    

내 질문은, 인 문자열을 선언 어쨌든 거기에 말함으로써 메모리를 할당하는 경우에도 문자열을 선언하는 말? 이와 같은 예에서와 같이 당 https://stackoverflow.com/a/1704433/1814023

  • ,

    char s[]="hello"; 
    

어레이는 복사 후 읽기 전용 영역에 배치된다. 이 같은 문자열의 주소를 인쇄하는 C에서 유효합니까?
printf("%p\n", &"Hello There"); // I tried, it prints some address 

과 같은 주소를 인쇄이

printf("%p\n", &"Hello There"); 
printf("%p\n", &"Hello There"); 

을 수행하여

. 느낌은 무엇입니까, 그것은 다른 주소를 인쇄해야합니다. 컴파일러가 여기에서 최적화를하고 있습니까?

답변

14

C 표준, §6.4.5 문자열 리터럴의 내용 :

해당 배열의 요소가 인 경우 이러한 배열의 구분 여부는 지정되지 않습니다.

동일한 내용을 가진 두 개의 문자열 리터럴은 동일한 배열을 나타낼 수 있으며 그 주소를 인쇄하면 동일한 포인터 값이 두 번 나타납니다. 이것을 결정하는 것은 컴파일러와 링커의 몫입니다. 나는 두 개의 별도의 모듈 ...

// main.c 
#include <stdio.h> 

extern void print_foo_addr(void); 

int main() 
{ 
    printf("%p\n", &"foo"); 
    print_foo_addr(); 
    return 0; 
} 

// printfoo.c 
#include <stdio.h> 

void print_foo_addr() 
{ 
    printf("%p\n", &"foo"); 
} 

으로 다음 프로그램을 컴파일 할 때 ... 나는 두 개의 서로 다른 포인터 값 (리눅스에 GCC 4.7.3)을 얻을 수 있지만, 때를 print_foo_addr에 대한 정의를 main.c에 넣으면 같은 값을 두 번 얻습니다. 그래서 그렇습니다. 표준에 의해 명시 적으로 허용되는 최적화이지만, GCC는 적어도 모듈별로이 최적화를 수행합니다.

+0

어쨌든 문자열 변수를 선언 할 수 있습니까? – StackIT

+0

문자열 변수를 선언 할 수 있다고 생각하지 않습니다. 문자열 변수는 항상 정의됩니다. 나 맞아? – StackIT

+1

@Patil : "string variable"은 무엇을 의미합니까? char의 배열이나 char에 대한 포인터를 가질 수 있습니다. 그것들은 각각 선언 될 수 있습니다. 배열에 null 문자가 포함되어 있고 해당 null 앞에 오는 모든 값이 특정 문자 집합의 값 (또는 char *이 가리키는 값에 대해 동일하게 유지되는 경우) 인 경우 변수를 "문자열"이라고 부를 수 있습니다. –

3

이것은 특히 C 표준에서 허용됩니다.

6.4.5p5-6

: 변환 단계 7

는 바이트 또는 제로 값의 부호는 문자열에서 문자 또는 리터럴 결과 각 바이트 문자 시퀀스에 추가된다. 그런 다음 멀티 바이트 문자 시퀀스를 사용하여 시퀀스를 포함하기에 충분한 정적 저장 기간 및 길이의 배열을 초기화합니다. ...

요소가 적절한 값을 갖는 경우 이러한 배열이 구분되는지 여부는 지정되지 않습니다.

+3

이 질문에 대한 내용은 C – moooeeeep

+0

C와 관련하여 설명 할 수 있습니까? – StackIT

+0

와우, 예. 결정된. – aschepler

0

"Hello There" 문자열 리터럴이며 문자열 테이블 (printf에서 "Hello There" 위해 같은 주소를 얻는 뒤에 그 이유)에서 사용할 수 있습니다.

당신이

char p2[] = "String"; 

메모리가 할당되며, "문자열"새로 생성 된 메모리에 복사됩니다 수행 할 때. 그러나

char * p3 = "String";은 읽기 전용 섹션을 가리 킵니다. 즉 문자열 테이블.

이 경우 p3&"String"을 인쇄하면 과 동일하게이됩니다.

p2&"String"을 인쇄하면 다른 주소가 인쇄됩니다. p2은 스택 주소이기 때문에.

0

리터럴 문자열은 특수 섹션에 배치되며 읽기 전용이어야합니다. 또한 여러 위치에서 동일한 문자열 리터럴을 사용하는 경우 컴파일러는 일반적으로 해당 문자열의 인스턴스를 하나만 만들 수 있습니다.

printf("%p\n", &"Hello There"); 
printf("%p\n", &"Hello There"); 

그러나이에 의존 할 수 없다, 그것은 또는 일어날 수있는 컴파일러 최적화 때문에 :이 예제에서 같은 ADRESS를 볼 이유입니다.

+0

BSS는 일반적으로 0으로 초기화 된 정적 데이터에 사용됩니다. 상수 데이터는 종종 코드가있는 텍스트 섹션으로 이동합니다. – Dipstick

+0

@Dipstick, 네가 맞다. 나는 그것을 제거했다. – Devolus