Thắc mắc về con trỏ và ô nhớ

Đây là 1 đoạn code tìm ra từ dài nhất trong xâu của 1 mod đã cho em. Cho em hỏi dòng str += i(Dòng em cmt ??? ấy ạ) có phải là nhảy i ô nhớ rồi gán cho mảng str bắt dầu từ ô nhờ vừa nhảy đến không ạ?
Theo như em biết thì đã là mảng hằng (const char) thì ko thay đổi bất kì thứ tự hay giá trị nào đó trong mảng mà sao trong trường hợp này lại đc ạ.

#include <stdio.h>
#include <ctype.h>

void longest_sub_string(const char *str) {
    const char *s = str;
    char len = 0;
    
    while (*str) {
    	
        while (!isalnum(*str)) ++str; // step over space
        
        int i = 0;
        while ( isalnum(str[i])) ++i;// last i = lenght of current word
		
        if (i > len) {//i vs lenght of the longest word
            s = str;
            len = i;
        }
        str += i;//????
    }
    // print
    for (const char *c = s; c < s + len; ++c) putchar(*c);
    puts("\n");
}


int main() {
    char s[1000];
    
    fgets(s, 999, stdin);
    
    longest_sub_string(s);
}

Mấy hôm trước em không để ý lắm nhưng khi em chạy đoạn code bên dưới thì phát hiện ra em hiểu sai cái gì đó và cái lệnh str += i không hợp lệ trong program em chạy thử:

#include <stdio.h>

int main(){
	char arr[]={"Hello world!"};
	arr += 3;
	
	puts(arr);
	  return 0;
}

nó báo lỗi là :

6	6	C:\Users\hp\Desktop\Cprograming\test\string.c	[Error] invalid operands to binary + (have 'char[13]' and 'int')

Mong các anh giúp đỡ ạ.

Đầu tiên em hiểu đơn giản thì con trỏ là biến để lưu địa chỉ của cái gì đấy. Cái gì đấy ở đây là địa chỉ của một biến, một hàm, một mảng, con trỏ khác, hay bất cứ thứ gì nằm trên bộ nhớ RAM. Địa chỉ chính là vị trí của dữ liệu. Có được nó thì ta có thể tương tác với nó. Không những tương tác với dữ liệu nội tại của phần mềm mà có thể tương tác với cả dữ liệu của những chương trình khác.

Phép +,- với một con trỏ là ta đang thay đổi cái địa chỉ mà con trỏ đang giữ. Hình dung là mỗi byte dữ liệu trên bộ nhớ RAM sẽ xếp thành hàng đơn và địa chỉ sẽ đánh từ đầu đến cuối hàng. Giảm địa chỉ thì sẽ chỉ đến người phía trước, tăng thì chỉ vào người đến sau. Phép +,- sẽ tăng giảm bao nhiêu dựa vào kiểu dữ liệu của con trỏ và giá trị mà ta +,- vào.
Ví dụ có str là con trỏ kiểu char và đang bằng 0 thì str++ sẽ chỉ đến ô thứ 1 vì char có 1 byte.
Nhưng nếu str là con trỏ kiểu int thì str++ sẽ chỉ đến ô số 4 vì int có 4 byte.

Mảng và con trỏ là khác nhau mặc dù có một số cách viết giống nhau nên không thể dùng phép +,- như con trỏ. Em giống như con trỏ đứng im cầm cái bút láer chỉ các mục tiêu. Phép cộng trừ giống như thay đổi mục tiêu thôi. Dễ dàng và hợp lệ.
Còn cái mảng khi nó được cấp phát giống như cái dãy nhà đã đặt móng thì không mang vác di chuyển đi đâu được nữa.

4 Likes

vậy thì dòng này nghĩa là sao ạ. Liệu có phải nhảy i ô nhớ trong xâu str không ạ? Code vẫn chạy bình thường nên em vẫn ko hiểu lắm

Nghĩa là con trỏ này sẽ trỏ đến một vị trí cách vị trí hiện tại n đơn vị. n phụ thuộc i và kiểu dữ liệu của str.

n = i * độ rộng của kiểu dữ liệu str.
Dương thì dịch về sau, âm thì dịch về trước.

Hình dung chuỗi string của em có 100 ký tự như một hàng 100 người.
str = 50 thì là str đang chỉ đến người thứ 51 (vì chỉ số bắt đầu từ 0).
Bây giờ str+=i mà i= 7 thì str sẽ có giá trị 57. Tức là sau lênh đó str sẽ trỏ vào người thứ 58.

1 Like
#include <stdio.h>

int main()
{
    char a[13] = "Hello";
    const char* s = a; // Từ mảng sang con trỏ
    char* x = a;
    a += 2; // Lỗi
    s += 3;
    x += 4;
    a[0] = '1';
    s[0] = '2'; // Lỗi
    x[0] = '3';
    *a = 'A';
    *s = 'B'; // Lỗi
    *x = 'C';
    printf("%s %s %s", a, s, x);
    return 0;
}

Đấy gọi là ngầm định, có một số cách dùng của mảng và con trỏ giống nhau, nhưng có 1 số cách dùng nó khác nhau.

3 Likes

Em hiểu cái này rồi ạ. Vậy còn khi sử dụng lệnh puts(s) thì giá trị đc in ra sẽ hiểu là các giá trị nằm trong con trỏ s về sau đúng không ạ.

Nó không in giá trị nằm trong con trỏ s. Con trỏ s nó không lưu cái gì ngoài địa chỉ bộ nhớ. Địa chỉ đó là vị trí bắt đầu của một chuỗi ký tự.
Hàm đó sẽ đẩy lần lượt các ký tự bắt đầu từ vị trí mà s đang trỏ tới cho tới khi gặp ký tự 0 thì dừng.

4 Likes

Em cảm ơn, em hiểu rồi ạ.

E có phân biệt dc mấy cái này ko ?

const char * s;  // pointer is changeable, entity is constant
char const * s; // same as above
char * const s: // pointer is constant, entity is changeable
const char * const s; // pointer and entity are constant

Tóm cái váy lại như này cho dễ hiểu.

  1. Trong khai báo type *var, thì var là pointer, *var là thực thể(giá trị của nơi mà var trỏ tới), thì :
  2. Const nằm ở trước thằng nào thì thằng đó là const.
    (lược bỏ cái type đi là dễ nhìn ra hơn)
4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?