Насколько я знаю, я знаю, что динамически размещенные строковые литералы не могут быть изменены во время выполнения, иначе вы столкнетесь с ошибкой сегментации.
Это связано с тем, что динамически размещенные строковые литералы хранятся, как я видел в коде сборки, в сегменте .rodata
, помещая эти литералы в то, что я интерпретирую как постоянную память.
Так что теоретически это никогда не должно работать на то, что, я надеюсь, есть в каждом современном компиляторе C:
#include <stdio.h>
#include <stdlib.h>
int
main( void )
{
char *p = ( char * )malloc( 10 * sizeof( char ) );
if ( p == NULL )
{
puts( "Bad memory allocation error!" );
return( EXIT_FAILURE );
}
else
{
p = "literal";
printf( "%s\n", p );
p[0] = 't'; // <-- This should cause a segmentation fault!
printf( "%s\n", p ); // <-- This should never reach execution!
}
return( EXIT_SUCCESS );
}
Однако, изучив, как работают tolower()
и toupper()
. Мне довольно трудно понять, как эти две простые функции способны делать то, что я думал, долгое время было невозможно. Вот что я имею в виду:
#include <stdio.h>
int
tolowercase( int c )
{
return ( c >= 'A' && c <= 'Z' ) ? ( c + 32) : ( c );
}
int
retstrlen( char *str )
{
int len = 0;
while( *str != '\0' ) { len++; str++; }
return( len );
}
int
main( int argc, char **argv )
{
for( int i = 0; i < argc; i++ )
{
for( int j = 0; j < retstrlen( argv[i] ); j++ )
{
argv[i][j] = tolowercase( argv[i][j] );
printf( "%c", argv[i][j] );
}
printf( "\n" );
}
return 0;
}
Как исходный код, определенный в моей пользовательской функции tolower()
, не вызывает ошибку сегментации, как это обычно происходит при манипулировании динамически размещаемыми строковыми литералами?
Моя единственная гипотеза, которую я могу нарисовать, состоит в том, что, поскольку tolowercase()
имеет параметр int и возвращаемый тип int, тогда компилятор выполняет преобразование типа, которое косвенно манипулирует ** argv.
Я почти уверен, что нахожусь на правильном пути в этом вопросе, но я мог бы неправильно понять всю мою терминологию, так что же на самом деле происходит с ** argv?