-5

What is wrong with the following lines?

//Thanks to Mark
#include <string.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
char datfile[127];
if(argc < 2) return -1;
strcpy_s(datfile, strlen(argv[1]), argv[1]);
strcat_s(datfile, strlen(argv[1]) + 4, ".dat");
printf("%s\n",datfile);//the warning appears here (why?)
return 0;
}

It shows Warning C4047 'function': 'const char *' differs in levels of indirection from 'char'

I've gone through the documentation provided by MSDN for C4047. It names a term called levels of indirection. I've gone through some discussions related with this topic i.e. levels of indirection in the web and (as a newbie) I found those beyond the scope of my radar.

I'd be very glad if someone points out the problem with the code above and provides a simply understandable explanation of the term level of indirection.

AAK
  • 3
  • 5
  • 1
    Wrong quotes. Use `"` for string literals. – Mat Nov 19 '16 at 08:14
  • 3
    Also, the second parameter in both cases should be the number of elements in the *destination*, not the source, e.g. 127. See https://msdn.microsoft.com/en-us/library/td1esda9.aspx. – Mark Tolonen Nov 19 '16 at 08:20
  • @Mat `"` thanks. Now it says `...differs in levels of indirection from 'char'` – AAK Nov 19 '16 at 08:26
  • Don't edit your question into a new question. It invalidates previous comments/answers. Plus, provide a [minimal, complete, verifiable example](https://stackoverflow.com/help/mcve). Your new error isn't reproducible with the code shown. – Mark Tolonen Nov 19 '16 at 08:32
  • 1
    I keep seeing people use the "safe" `strcpy_s()` or `strcat_s()`. I've never seen them used correctly... – EOF Nov 19 '16 at 08:36
  • I see correct use as long as people RTFM. – Mark Tolonen Nov 19 '16 at 08:44
  • This line in the [example](https://msdn.microsoft.com/en-us/library/td1esda9.aspx) given by MSDN `strcat_s( string, "strcpy_s " ); ` generates `C2198: Too few arguments`...! – AAK Nov 19 '16 at 08:45
  • @AAK The example is `crt_strcpy_s.cpp`. If you use compile as C++ it works because it uses a template version of `strcpy_s`. Again, **provide a verifiable example**. – Mark Tolonen Nov 19 '16 at 08:47
  • @MarkTolonen I want `strcpy_s` to read the exact no. of characters in `argv[1]` that's why `strlen` was used. Would plz you specify the required **verifications**. – AAK Nov 19 '16 at 08:59
  • @AAK make a complete compilable example that gives the error described. – Mark Tolonen Nov 19 '16 at 09:01
  • @AAK `strcpy_s` does that by default. With your code, if the argument is `abc`, you tell the compiler "`datfile` is 3 bytes long (from strlen), but the string to be copied is null terminated (4 bytes long) and at runtime the code will call the invalid parameter handler. The 2nd parameter is the **length of the destination buffer**. – Mark Tolonen Nov 19 '16 at 09:05
  • This is very unfortunate to see that the question being downvoted without asking for any revise. and no one even explaining how to improve it. If the question doesn't comply with the community standards then it deserves to be downvoted. Will it be an unfair call to ask for explanation that why the question was down voted? Mark has suggested an edit though, he is proactive; when I got the point that he was asking for, I started to work for that. In the mean time he posted the answer with an example. I appreciate it, and of course I acknowledge it. – AAK Nov 19 '16 at 16:00
  • The verifiable example of the original error that I posted in the answer is what you should have posted in the question...An example that compiles and reproduces the error. Please read the link I posted above about an [MCVE](https://stackoverflow.com/help/mcve). If fact, after your edit, the above sample code, if made to compile, doesn't produce the error described now. It would be better to revert the edit. – Mark Tolonen Nov 19 '16 at 18:34
  • http://cboard.cprogramming.com/c-programming/100619-warning-c4013-errrrrr-2.html – AAK Nov 20 '16 at 20:54

1 Answers1

1

Verifiable example of original error:

#include <string.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    char datfile[127];
    if(argc < 2)
        return -1;
    strcpy_s(datfile, strlen(argv[1]), argv[1]);
    strcat_s(datfile, strlen(argv[1]) + 4, '.dat');
    printf("%s\n",datfile);
    return 0;
}

Output of VS2015 (cl /nologo /W4 test.c):

test.c
test.c(10): warning C4047: 'function': 'const char *' differs in levels of indirection from 'int'
test.c(10): warning C4024: 'strcat_s': different types for formal and actual parameter 3

"level of indirection" indicates mismatch in pointer level. int, int*, int** have different levels of indirection.

With @Mat suggestion this the following line changed to double quotes:

strcat_s(datfile, strlen(argv[1]) + 4, ".dat");

Compiles with no warnings but crashes due to incorrect parameter use. The 2nd parameter to strcpy_s and strcat_s is the length of the destination buffer, not the source string length. Since strlen(arg[v]) doesn't include the nul terminator, the strcpy_s will fail because it will try to copy one more byte than indicated.

Correct use of the 2nd parameter:

#include <string.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    char datfile[127];
    if(argc < 2)
        return -1;
    strcpy_s(datfile, sizeof datfile, argv[1]);
    strcat_s(datfile, sizeof datfile, ".dat");
    printf("%s\n",datfile);
    return 0;
}

Output:

C:\>cl /nologo /W4 test.c
test.c

C:\>test abc
abc.dat
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • and what is `level of indirection`? – AAK Nov 19 '16 at 10:15
  • "level of indirection" indicates a difference in pointer type. `int, int*, int**, int***` are all different levels of indirection. – Mark Tolonen Nov 19 '16 at 10:26
  • @AAK, please make an [MCVE](https://stackoverflow.com/help/mcve) and ask a new question. I don't know how to reproduce your C4042 results. The code as posted above does not produce that. – Mark Tolonen Nov 19 '16 at 18:35
  • @AAK No, did you read the link? Make a compilable small example that reproduces the error. Ask a new question because it is a new error. The question should look like the top half of this answer...A small example with the exact error message. – Mark Tolonen Nov 19 '16 at 18:37
  • yes... I've gone through that thoroughly... – AAK Nov 19 '16 at 18:42