这可能是一个初学者的问题,但它让我感到困惑。我知道在c中,数组本身就是指向数组第一个元素的指针。请考虑以下示例
char *words[LENGTH];
words[0] = "zero";
words[1] = "one";
words[2] = "two";
printf("%s\n",*words);
最终打印的内容是zero
。但是,我的理解是words
是指向words
数组的第一个元素的指针,它是一个char指针=> words
是指向char的指针。因此*words
将成为char的指针。因此我希望在这里打印一个内存地址而不是实际的字符串。我在这里误解了什么?
答案 0 :(得分:3)
我理解在c中,数组本身就是指向数组第一个元素的指针。
这是不正确的 - 在大多数情况下,表达式类型为" N元素数组T
"将转换为"指向T
"的类型的表达式,但数组对象本身不是指针。没有为指针留出存储空间作为数组对象的一部分。
字符串文字 "zero"
具有char
"类型" 5元素数组,而"one"
和{{1}具有"two"
"的类型" 4元素数组; (因为字符串以零值字符结尾,所以需要N + 1个元素来存储N字符串。)
每个字符串文字都是一个数组表达式,但由于这些表达式不是char
或一元sizeof
运算符的操作数,并且因为它们不用于初始化字符数组,所以每个表达式都是< em>将转换为指针表达式,每个表达式的值是数组中第一个元素的地址。
因此我希望在这里打印一个内存地址而不是实际的字符串。我在这里误解了什么?
&
转换说明符告诉%s
打印从指定地址开始的字符序列,直到看到字符串终结符 - 这就是为什么您将printf
视为输出而不是地址。要打印指针值,您可以使用zero
转换说明符,如下所示:
%p
答案 1 :(得分:2)
你对printf所取得的成就的理解是正确的 - 正如你所写的,*words
实际上是指向char的指针。 %s
格式说明符用于打印字符串,因此它假定您传递的任何指针实际上是以'\0'
字符结尾的字符数组 - 格式c用于存储字符串。有了这些信息,printf知道它应该只打印数组中的所有字符,直到它找到'\0'
- 这正是它在这种情况下所做的。如果你想打印那个指针的地址,那么正确的格式说明符就是(如Stargateur的回答中提到的那样)%p
。
答案 2 :(得分:2)
由于@Stargateur回复你需要使用%p标志并使用(void *)。 请注意,它会显示第一个字符串的起始地址(&#39;零&#39;),下一个代码将遍历所有字符串并打印其地址(将3个字符串视为2D(二维) )具有不同长度的字符串数组。
#include <stdio.h>
#define LENGTH 3
int main(void)
{
char *words[LENGTH];
words[0] = "zero";
words[1] = "one";
words[2] = "two";
int len = 0;
while(len<(int)LENGTH)
{
printf("%s\n", words[len]);
printf("%p\n", (void *)words[len]);
len++;
}
printf("\n%p\n", (void *)*words); // prints the first address only (the 'zero' address)
return 0;
}
答案 3 :(得分:1)
你很接近你是对的,c-string是一个指针,它包含字符串第一个字符的地址。 c-string不是字节而是地址。 printf标志%s
期望这些字节的地址。所以你确实给了printf()
一个地址,但你要求printf()
显示c-string的值。所以“零”。您唯一的错误是您没有阅读printf()
手册。
如果您想要地址,请尝试:
printf("%p\n", (void *)*words);
答案 4 :(得分:1)
app.directive('upload', ['$lhttp', '$http', '$interval', '$timeout', '$q', '$location', function ($lhttp, $http, $interval, $timeout, $q, $location) {
return {
templateUrl: '/.src/views/upload-widget.html',
controller: function($scope, $element, $attrs) {
// code ...
// Define upload function
vm.uploadFiles = ()=>{
// code ...
// Create the payload for the upload request
let formdata = new FormData();
formdata.append("salt", salt);
// code ...
// Create the upload request
let request = $http({
method: 'POST',
url: "/.src/php/upload.php",
data: formdata,
transformRequest: angular.identity,
uploadEventHandlers: {
progress: function(e) {
vm.progress = Math.round((e.loaded/e.total)*100) + "%";
if (vm.progress === '100%') vm.get_server_progress(salt);
}
},
headers: {'Content-Type': undefined}
});
// Create handler functions for success and errors
request.then(function successCallback (response) {
vm.server_progress = "100%";
vm.actually_loading = false;
$timeout(()=>{ vm.loading = false }, 600);
if (response.data.error.length) {
vm.fail = true;
vm.error_message = response.data.error;
}
if (!response.data.log.length) {
vm.fail = true;
vm.error_message = $scope.m.text.upload_error;
}
}, function errorCallback (response) {
// code ...
});
}
// code ...
// Create function for checking status of server side processing of the upload
vm.get_server_progress = (salt)=>{
$http.get('/.src/php/status.php?salt='+salt+'&d='+Date.now()).success((data)=>{
vm.server_progress = data+"%";
re_get_progress_if(salt);
}).error(()=>{
re_get_progress_if(salt);
});
}
function re_get_progress_if (salt) {
//////////////////////////////////////
// THIS IS THE PROBLEMATIC $TIMEOUT://
if (vm.actually_loading) $timeout(vm.get_server_progress, 100, true, salt);
}
},
controllerAs: 'up'
};
}]);
定义了一个char *数组,即char **。 char *words[LENGTH];
等于*words
,表示&#34;零&#34;。
创建这样的char *数组是不安全的。例如,以下代码编译正常,但其行为未定义。
words[0]
答案 5 :(得分:1)
*
(乘法中不是*
)很重要的上下文,
当在declearation中使用时,如char *words[LENGTH]
中的单词成为char的指针数组。
就指针而言*
地址运算符的值时,它会将值存储在特定地址,而&
是地址运算符,给出变量的地址。
printf("%s\n",*words) // prints value at address to which word points
,而
printf("%p\n",words) // prints address to which word points