programing

(및 배열)의 크기는 얼마나 됩니까?

jooyons 2023. 10. 27. 21:55
반응형

(및 배열)의 크기는 얼마나 됩니까?

다음 질문을 따릅니다.어레이의 주소가 C의 값과 동일한 이유는 무엇입니까?

#include <stdio.h>
#define N 10    
char str2[N]={"Hello"};
int main(){
    printf("sizeof(str2): %d bytes\n", sizeof(str2));
    printf("sizeof(&str2): %d bytes\n", sizeof(&str2));
    return 0;
}

출력:

sizeof(str2): 10 bytes
sizeof(&str2): 4 bytes

나는 그것을 알고 있습니다.str2alone은 배열된 첫번째 요소의 주소입니다.str2. 그리고 언제str2의 논쟁입니다.sizeof전체 배열 str2의 크기를 반환합니다.

외에 .&str2또한 arr의 첫번째 요소의 주소입니다.str2유형이 다릅니다(char (*)[N]== pointer to array).그런데 어떻게.&str2의 논쟁일 때는 행동합니다sizeof?

사이의 차이&str그리고.str,언제str로 선언됩니다.char str[10]?

연산자 읽기:

6.5.3.4 , 1125:
때 바를 때.sizeofoperator to array type의 결과는 배열의 총 바이트 수입니다.

그래서, 당신의 선언에 의하면,sizeof(str2)는 10바이트의 전체 배열 크기를 제공합니다(N은 10으로 정의되고 문자 크기는 1바이트이기 때문입니다).
반면에 표현에 있어서는sizeof(&str2),&str2는 배열의 주소이며 해당 주소의 크기는 시스템에서 4바이트입니다.(일부 시스템에서는 주소 크기가 8바이트(예: 64비트)일 수 있습니다.)

외에 .&str2또한 arr의 첫번째 요소의 주소입니다.str2?

아니요, 값 단위로 둘 다&str2그리고.str동일하지만 의미론적으로 둘 다 다릅니다.하나는 10자 배열의 주소이고 다른 하나는 1자 배열의 주소입니다.

그들 사이에 있는 자신의 에서 본 한 가지 차이점은 (@ouah가 이것을 대답으로 설명했다)입니다.

  • 유형의str이다.char[10]
  • 유형의&str이다.char(*)[10]

둘째: 다이어그램을 따르는 것이 다른 차이를 관찰하는 데 도움이 됩니다.

for declaration: 
#define N 10
char str2[N] = {"Hello"};

str2 Array in memory is something like:
----------------------------------------

str
+----+----+----+----+----+----+----+----+----+----++----+
|'H' |'e' |'l' |'l' |'o' |'\0'|'\0'|'\0'|'\0'|'\0'|| '@'|
+----+----+----+----+----+----+----+----+----+----++----+
 201   202  203 204  205   206  207  208  209  210   211
▲ ▲     ▲                                             ▲
| |     |                                             |
|(str2) (str2 + 1)                                    | 
|                                                     |
|-----------------------------------------------------|
|201                                                  | 
|                                                     |
|                                                     |
(&str2) = 201                           (&str2 + 1) = 211


* assuming str address start from 201
* str[N] is 10 char long 201-210, partially initialized
* at uninitialized position, str2[i] = '\0'
* location 211 is unallocated, having garbage value,
  access to this location is illegal-Undefined Behavior

위 다이어그램에 대해 다음과 같은 코드를 작성할 수 있습니다.

#include <stdio.h>
#define N 10    
int main(){
   char str2[N]={"Hello"};
  
   printf("\n %p, %p\n",str2, str2+1);
   printf("\n %p, %p\n",(&str2), (&str2+1));
}  

출력:

 0xbf67e142, 0xbf67e143

 0xbf67e142, 0xbf67e14c

코드패드 링크:

첫 번째 줄에서는 출력 주소가 1바이트 차이가 나지만, 두 번째 줄에서는 배열의 포인터이기 때문에 10바이트 차이가 납니다(위의 다이어그램에 나와 있음).

포인터 산술의 규칙에 따르면 포인터 변수에 1을 추가하면 해당 변수는 자신의 유형의 다음 요소를 가리키기 시작합니다.그래서 10바이트 차이가 나는 이유는&str2는 배열을 가리키는 주소입니다.

번째 차이:

함으로써*str2첫번째 요소에 접근할 수 있습니다.반면에.*(&str2)첫번째 요소를 제공하지 않으며, 대신 첫번째 요소의 주소를 제공합니다.

여기에는 다음과 같은 예가 도움이 됩니다.

#include <stdio.h>
#define N 10    
int main(){
   char str2[N]={"Hello"};
   printf("\n%p %c, %p %c\n",str2, *(str2), *(&str2), **(&str2));
}  

출력:

0xbf587046 H, 0xbf587046 H

코드패드 링크

출력중

str2 gives  0xbf587046 
*(str2)     H 
*(&str2)    0xbf587046 
**(&str2)   H 

은 .*(&str2) == str2값은 주소입니다.서.*(str2) = **(&str2)H.

편집: 위에서 다음과 같은 차이점을 나타냈습니다.&str그리고.str어디에str는 유형의 배열입니다.char[10].

사이의 차이char *str그리고.char str[]그리고 둘 다 기억 속에 어떻게 저장되어 있는지.

다음과 같은 두 가지 선언이 있다고 가정합니다.

char *str1 = "hello";   
char str2[] = "hello";  

위 선언문에서str1에 대한 포인터입니다.char, (첫 번째 문자의 주소를 보유함으로써) 일정한 문자열 리터럴을 가리킵니다.h인에"hello"문자열).

C에 있는 문자열은 다음과 같습니다.char[N](배열) 유형이 그 이유입니다.sizeof("hello")6을 주는 이유는"hello"문자열은 6자 길이 배열(\0은 null,료, helloochar[6]).

당신을 추모합니다."hello"문자열은 다음과 같이 저장됩니다.

 str1         23   24   25   26   27   28
+----+      +----+----+----+----+----+----+
| 23 |      | h  | e  |  l | l  | o  | \0 |    
+----+      +----+----+----+----+----+----+
   +-----------▲

here the address of the hello string is the first address = 23.  
str1: is a pointer capable of storing an address. 
"hello" consists of 6 chars

char* str1 = "hello";기본적으로 문자열 hello의 주소를 포인터 변수에 저장합니다.str1위 그림에서 보는 바와 같이

참고: 원하는 경우 변경할 수 있습니다.str1다른 끈을 가리키기 위해서요하지만 수정할 수 없습니다.hello끈을 매다 다음 가 유효합니다예를 들어 다음 코드가 유효합니다.

 char* str1 = "hello";  // str1 points to hello  str1-->"hello"
 str1 = "world";  //Now, str1 points to world  str1-->"world"

지금이다str1다른 일정한 문자열 세계를 가리킵니다.

 str1         93   94   95   96   97   98 
+----+      +----+----+----+----+----+----+
| 93 |      | w  | o  |  r | l  | d  | \0 |    
+----+      +----+----+----+----+----+----+
   +-----------▲

here address of world string is first address = 93.  
str1: value change to point string world. 

유의할 사항:str1일정한 문자열을 가리키므로 액세스/메모리 위치를 indexing하여 문자열을 수정할 수 없습니다.str1[i] = 'A'; 읽기 전용 메모리에 글을 쓰고 있기 때문에 불법이며 런타임에 이 동작이 정의되지 않습니다(구사적으로 정확하므로 컴파일 오류는 없음).

다시 한 번 말씀드리str1포인터입니다.sizeof(str1)같은 기계에 4개를 줄 겁니다.

나의 다음 코드와 실행:

#include <stdio.h>
int main(){
   char* str1="Hello";
   printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));
   str1 = "world";
   printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1));
   return 1;
}  

출력:

str1: Hello, address: 0x80485e8, sizeof(str1): 4
str1: world, address: 0x8048619, sizeof(str1): 4

코드패드 링크

그래서 새로운 문자열을 지정하기 위해서는 단순히 새로운 문자열의 주소를 지정합니다.하지만 전화를 할 수 없습니다.strcpy()그것은 읽기 전용 메모리 위치에 쓰려 할 것이며 불법입니다.

두번째 선언에서char str2[] = "hello";,str2[]입니다.\0종료된 문자 배열(또는 문자열)이지만 포인터는 아닙니다.이 선언 크기에는 기본 크기가 주어지지 않으므로 상수 문자열 "hello"의 크기가 6임을 알 수 있습니다.유형str2이다.char[6].

우리가 할때는char str2[] = "hello";char 배열이 생성되고 hello 문자열이 해당 배열에 복사됩니다. 그래서.str2는 단순히 포인터가 아니라 완전한 문자열을 저장하는 배열입니다.

개념적으로.

       str2:
       103  104  105  106  107  108
      +----+----+----+----+----+----+
      | h  | e  |  l | l  | o  | \0 |    
      +----+----+----+----+----+----+

이 경우 코드에서 할 수 없습니다.str2[] = "world";아니면str2 = "world", 컴파일 타임 에러가 될 것입니다.

예제 코드:

#include<stdio.h>
int main(){
 char str2[] = "hello";
 str2[] = "world";
 str2 = "world"; 
 return 1; 
}

컴파일 오류:

In function 'main':
Line 4: error: expected expression before ']' token
Line 5: error: incompatible types in assignment

코드스케이프 링크

이 배열 위치str2를 들어다를 등 할 수 . 예를 들어 내용을 수정할 수 있습니다.str2[2] = 'A'완벽하게 유효합니다.strcpy를 호출하여 내용을 변경할 수도 있습니다(주소 공간은 변경되지 않습니다).

       strcpy(str2, "world");

       str2:
       103  104  105  106  107  108
      +----+----+----+----+----+----+
      | w  | o  |  r | l  | d  | \0 |    
      +----+----+----+----+----+----+

      Note that when "world" is copied into a same memory space, the addresses of both "world" and "hello"
      string are the same.  

코드 예제:

#include<stdio.h>
int main(){
 char str2[] = "hello";
 printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
 str2[2] = 'A';
 printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
 strcpy(str2, "world");
 printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2));
 return 1; 
}

출력:

str2: hello, address: 0xbf58d056, sizeof(str2): 6
str2: heAlo, address: 0xbf58d056, sizeof(str2): 6
str2: world, address: 0xbf58d056, sizeof(str2): 6

코드패드 링크

참고: 동일한 주소 공간에서 문자열 값이 다릅니다.sizeof(str2)= 6은 배열 크기(바이트 단위)인 기존 답변에서 완벽하게 이해할 수 있습니다.

2차원 배열에 대한 유사한 설명을 읽으려면 메모리에 와 와 와 둘 다 저장되는 방법의 차이를 읽어 보십시오.

&str2포인터입니다.따라서 플랫폼에서 포인터의 크기만 확인할 수 있습니다.

str2유형의char [10]즉, array)10 of

&str2유형의char (*)[10](즉, 배열에 대한 포인터)10char).

그렇게sizeof (&str2)포인터 유형의 객체 크기를 산출합니다.char (*)[10]

단순히 변수를 사용하는 경우arr(정의대로)char arr[10]), 항상 상수 포인터로 붕괴합니다.char *const arr첫 번째 요소를 가리킵니다.하는 동안에&arr포인터로 연결됩니다.char (*)[10]의 크기를 포함합니다.arr, 예를 들면10.

언급URL : https://stackoverflow.com/questions/15177420/what-does-sizeofarray-return

반응형