解析:
这道题考查的是 C 语言中**数组名**、**指针变量**以及**字符串常量**之间的赋值规则。
### 核心概念解析
1. **变量定义分析**:
* `char a[5]`:定义了一个字符数组 `a`,它包含 5 个字符空间。**数组名 `a` 是一个常量指针**(即地址常量),指向数组首元素的地址。在 C 语言中,**数组名不能作为左值被赋值**,也就是说不能改变 `a` 的指向。
* `*p = a`:定义了一个字符指针 `p`,并将其初始化为指向数组 `a` 的首地址。`p` 是一个**指针变量**,它的值(即它存储的地址)是可以改变的。
2. **选项逐一分析**:
* **A. `p="abcd";` 【正确】**
* `"abcd"` 是一个字符串常量,它在内存中占据一段空间,并返回该字符串首字符 `'a'` 的地址。
* `p` 是一个指针变量,可以存储地址。
* 这条语句的作用是将指针 `p` 的指向从原来的数组 `a` 改为指向字符串常量 `"abcd"` 的首地址。这是完全合法的指针赋值操作。
* *注意:虽然语法正确,但此时 `p` 不再指向数组 `a`。*
* **B. `a="abcd";` 【错误】**
* `a` 是数组名,代表数组的首地址,是一个**地址常量**。
* C 语言规定,**不能对数组名进行赋值操作**。你不能改变数组 `a` 本身的地址。
* 如果想把字符串拷贝到数组 `a` 中,应该使用 `strcpy(a, "abcd");`,而不是直接赋值。
* **C. `*p="abcd";` 【错误】**
* `*p` 表示指针 `p` 当前所指向的**内容**(即一个 `char` 类型的变量)。
* `"abcd"` 是一个字符串常量的**地址**(类型是 `char *`)。
* 这条语句试图将一个**地址**(指针类型)赋值给一个**字符变量**(`char` 类型),类型不匹配。
* 即使忽略类型警告,这也意味着想把整个字符串的地址塞进一个字节的空间里,逻辑上也是错误的。如果想赋值字符,应该是 `*p = 'a';`。
* **D. `*a="abcd";` 【错误】**
* 首先,`*a` 等价于 `a[0]`,表示数组第一个元素的**内容**(`char` 类型)。
* 同样,`"abcd"` 是地址(`char *` 类型)。
* 存在与选项 C 相同的类型不匹配问题:不能将地址赋值给字符变量。
* 此外,虽然 `*a` 可以作为左值修改数组内容(如 `*a = 'x';`),但右边必须是字符或整数,不能是字符串地址。
### 总结
* **数组名**是常量,不能被赋值(排除 B)。
* **指针变量**可以被赋值为一个新的地址(A 正确)。
* **解引用后的指针/数组元素**(`*p` 或 `*a`)是字符类型,只能接收字符或整数值,不能接收字符串地址(排除 C、D)。
因此,正确答案是 **A**。