Я пытаюсь получить pid, используя этот код. Но когда я запустил скомпилированный код. Я получаю сообщение об ошибке «предупреждение: формат указывает тип« unsigned long », но аргумент имеет тип« pid_t »(также известный как« int »)[-Wformat]».
Когда я изменил спецификатор формата на просто «%lu», он печатается без дополнительного символа.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid = getpid();
printf("pid: %lun", pid);
}
Я ожидал pid «60316». Я получаю pid «60316n».
И что вы ожидаете от n в %lun? Это должно было быть \n? — person jennylearner schedule 04.10.2019
n не является частью спецификатора формата %lu; это часть обычной строки. Распечатывается как есть. — person jennylearner schedule 04.10.2019
В дополнение к комментарию UnholySheep, %lu специально используется для печати unsigned long, последующее n просто обрабатывается как строковый литерал, точно так же, как префикс pid :. — person jennylearner schedule 04.10.2019
Хорошо. Я понял теперь. Спасибо всем за то, что сделали это яснее. — person jennylearner schedule 04.10.2019
nпечатает по той же причине, что иpпечатает.nне является частью спецификатора.В стороне:
Тип данных
pid_t– это тип целого числа со знаком, который способен представлять идентификатор процессаСм. Каков правильный спецификатор printf для печати pid_t?
Я проверил ссылку. Это было полезно. — person jennylearner; 04.10.2019
Строка формата, которую вы передаете
printf, представляет собой смесь обычных символов и описателей формата. Обычные символы печатаются сами по себе, а спецификаторы формата вызывают преобразование и печать одного из дополнительных аргументов. Но тип каждого дополнительного аргумента должен более или менее точно соответствовать типу, ожидаемому спецификаторами формата.Из предупреждающего сообщения мы можем сказать, что
pidявляетсяint. Таким образом, правильный спецификатор формата —%d.Спецификатор
%luбыл бы правильным, если быpidимел типunsigned long int.Спецификаторы формата — это своего рода миниатюрный язык программирования. Основной спецификатор формата для типа
unsigned int—%u, и вы можете изменить его для печатиunsigned long intвместо модификатораl(буква ell):%lu.Но когда вы пишете
%lun,nна самом деле не является частью какого-либо спецификатора формата, поэтому оно печатается как само по себе.(Кроме того, вам повезло: несмотря на несоответствие между типом
pidи спецификатором формата%lu, вы все равно получили разумное значение.)Как правило, выровнять аргументы и спецификаторы формата несложно:
intдля%d,unsigned intдля%uили%x,long intдля%ld,floatилиdoubleдля%fи т. д. Но какой спецификатор правильно использовать дляpid, который имеет типpid_t? Сегодня на вашем компьютереpid_tвыглядит какint, поэтому%dбудет правильным, но что, если на каком-то другом компьютере он будет иметь другой тип? Как написать один фрагмент кода, который будет корректно работать на любом компьютере? Один из способов — выбрать тип, который, вероятно, является правильным, и использовать спецификатор для этого типа, а затем использовать явное приведение для преобразования вашего значения в выбранный вами тип. Так:Или вот так:
Если приведение не требуется (если выбранный вами спецификатор формата уже верен для типа
pidна вашем компьютере), приведение не помешает.Наконец, поздравляю с использованием компилятора, который фактически выдал вам предупреждающее сообщение:
Слишком много начинающих программистов застряли на старых компиляторах, которые не выводят подобных предупреждений, и это, очевидно, значительно усложняет отслеживание проблем, вызванных несоответствием спецификаторов формата! (Ваш компилятор был особенно полезен тем, что он дал вам как видимый тип
pid, а именноpid_t, так и фактический базовый типint.)Так что я просто распечатал n. Теперь я понимаю. Спасибо — person jennylearner; 04.10.2019
Итак, я ошибаюсь, используя unsigned long для pid? Я думал, что это нормально, так как диапазон больше. — person jennylearner; 04.10.2019
Да, это неправильно. Если
pidдействительно является целым числом, строго говоря, неправильно печатать его как беззнаковое сu(хотя вам почти всегда это сойдет с рук). Печатать сlхуже, потому чтоpid(во всяком случае, на вашей машине) определенно недолго. Вам часто это тоже сойдет с рук на 32-битной машине, где иint, иlong intявляются 32-битными. (Но это не сработает на моей машине, гдеint— 32 бита, аlong— 64.) — person jennylearner; 04.10.2019