C/C++ static vs global

static has a very simple logic to it. If a variable is static, it means that it is a global variable, but it's scope is limited to where it is defined (i.e. only visible there). For example:

  • Outside a function: global variable but visible only within the file (actually, the compilation unit)
  • Inside a function: global variable but visible only within the function
  • (C++) Inside a class: global variable but visible only to the class

Now let's see what the C11 standard says regarding static and extern (emphasis mine):

6.2.2.3

If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.

6.2.2.4

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

6.2.2.7

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

So the standard says that first, if you have:

static int m; extern int m;

then the second declaration (with extern) would regard the first one and in the end m would still be static.

However, in any other case, if there are declarations with both internal and external linkage, the behavior is undefined. This actually leaves us with only one option:

extern int m; static int m;

i.e., extern declaration before static declaration. gcc was nice enough to give you error in this case of undefined behavior.

转载于:https://www.cnblogs.com/hustxujinkang/p/4525864.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里是使用ffmpeg库推流本地文件,并使用av_seek_frame实现跳转功能的完整C++代码: ```cpp #include <iostream> #include <string> extern "C" { #include <libavformat/avformat.h> #include <libavutil/mathematics.h> } #define STREAM_DURATION 10.0 #define STREAM_FRAME_RATE 25 /* 25 images/s */ #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */ /* add a video output stream */ static AVStream *add_video_stream(AVFormatContext *oc, enum AVCodecID codec_id) { AVCodecContext *c; AVStream *st; st = avformat_new_stream(oc, NULL); if (!st) { std::cerr << "Could not allocate stream" << std::endl; exit(1); } c = st->codec; c->codec_id = codec_id; c->codec_type = AVMEDIA_TYPE_VIDEO; /* put sample parameters */ c->bit_rate = 400000; /* resolution must be a multiple of two */ c->width = 352; c->height = 288; /* frames per second */ c->time_base = (AVRational) { 1, STREAM_FRAME_RATE }; st->time_base = c->time_base; c->gop_size = 12; /* emit one intra frame every twelve frames at most */ c->pix_fmt = STREAM_PIX_FMT; /* some formats want stream headers to be separate */ if (oc->oformat->flags & AVFMT_GLOBALHEADER) c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; return st; } /* open the output file, and allocate the format context */ static void open_output_file(const std::string &filename, AVFormatContext **oc, AVOutputFormat *fmt) { int ret; /* allocate the output media context */ avformat_alloc_output_context2(oc, fmt, NULL, filename.c_str()); if (!(*oc)) { std::cerr << "Could not create output context" << std::endl; exit(1); } /* add the video stream using the default format codecs and initialize the codecs */ add_video_stream(*oc, (*oc)->oformat->video_codec); /* open the output file, if needed */ if (!((*oc)->oformat->flags & AVFMT_NOFILE)) { ret = avio_open(&(*oc)->pb, filename.c_str(), AVIO_FLAG_WRITE); if (ret < 0) { std::cerr << "Could not open output file" << std::endl; exit(1); } } /* write the stream header, if any */ ret = avformat_write_header(*oc, NULL); if (ret < 0) { std::cerr << "Error occurred when opening output file" << std::endl; exit(1); } } /* close the output file and free the format context */ static void close_output_file(AVFormatContext *oc) { /* write the trailer, if any */ av_write_trailer(oc); /* close the output file */ if (!(oc->oformat->flags & AVFMT_NOFILE)) avio_closep(&oc->pb); /* free the stream */ avformat_free_context(oc); } /* seek to a specific frame in a video file */ static void seek_to_frame(AVFormatContext *fmt_ctx, int stream_index, int64_t timestamp) { int ret; /* seek to the timestamp */ ret = av_seek_frame(fmt_ctx, stream_index, timestamp, AVSEEK_FLAG_BACKWARD); if (ret < 0) { std::cerr << "Error seeking to timestamp " << timestamp << std::endl; exit(1); } /* flush the codec buffers */ avcodec_flush_buffers(fmt_ctx->streams[stream_index]->codec); } int main(int argc, char **argv) { if (argc != 2) { std::cerr << "Usage: " << argv[0] << " <output file>" << std::endl; return 1; } AVOutputFormat *fmt; AVFormatContext *oc; AVPacket pkt; int frame_count, i; double t, tincr; int64_t next_pts; /* register all codecs and formats */ av_register_all(); /* allocate the output media context */ fmt = av_guess_format(NULL, argv[1], NULL); if (!fmt) { std::cerr << "Could not determine output format" << std::endl; return 1; } open_output_file(argv[1], &oc, fmt); /* initialize the frame counter */ frame_count = 0; /* initialize the timestamp increment */ tincr = 2 * M_PI * STREAM_FRAME_RATE / STREAM_DURATION; next_pts = 0; /* main loop */ for (i = 0; i < 100; i++) { AVStream *st; AVCodecContext *c; AVRational time_base; AVFrame *frame; int got_packet = 0; int ret; /* get the video stream */ st = oc->streams[0]; c = st->codec; time_base = st->time_base; /* allocate a new frame */ frame = av_frame_alloc(); if (!frame) { std::cerr << "Could not allocate video frame" << std::endl; exit(1); } /* generate synthetic video */ frame->pts = av_rescale_q(frame_count, time_base, c->time_base); frame->format = c->pix_fmt; frame->width = c->width; frame->height = c->height; ret = av_frame_get_buffer(frame, 0); if (ret < 0) { std::cerr << "Could not allocate frame data" << std::endl; exit(1); } for (int y = 0; y < c->height; y++) for (int x = 0; x < c->width; x++) frame->data[0][y * frame->linesize[0] + x] = x + y + frame_count * 3; for (int y = 0; y < c->height / 2; y++) { for (int x = 0; x < c->width / 2; x++) { frame->data[1][y * frame->linesize[1] + x] = 128 + y + frame_count * 2; frame->data[2][y * frame->linesize[2] + x] = 64 + x + frame_count * 5; } } /* encode the frame */ av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); if (ret < 0) { std::cerr << "Error encoding video frame" << std::endl; exit(1); } /* if the frame was encoded, write it to the file */ if (got_packet) { pkt.stream_index = st->index; av_packet_rescale_ts(&pkt, time_base, st->time_base); ret = av_interleaved_write_frame(oc, &pkt); if (ret < 0) { std::cerr << "Error while writing video frame" << std::endl; exit(1); } } /* increase the frame count */ frame_count++; /* calculate the next presentation timestamp */ t = (double)frame_count / STREAM_FRAME_RATE; next_pts += (int64_t)(tincr * 1000); if (next_pts > (double)av_gettime()) { av_usleep(next_pts - av_gettime()); } /* free the frame */ av_frame_free(&frame); } /* seek to a specific frame */ seek_to_frame(oc, 0, 30); /* continue encoding frames */ for (; i < 200; i++) { AVStream *st; AVCodecContext *c; AVRational time_base; AVFrame *frame; int got_packet = 0; int ret; /* get the video stream */ st = oc->streams[0]; c = st->codec; time_base = st->time_base; /* allocate a new frame */ frame = av_frame_alloc(); if (!frame) { std::cerr << "Could not allocate video frame" << std::endl; exit(1); } /* generate synthetic video */ frame->pts = av_rescale_q(frame_count, time_base, c->time_base); frame->format = c->pix_fmt; frame->width = c->width; frame->height = c->height; ret = av_frame_get_buffer(frame, 0); if (ret < 0) { std::cerr << "Could not allocate frame data" << std::endl; exit(1); } for (int y = 0; y < c->height; y++) for (int x = 0; x < c->width; x++) frame->data[0][y * frame->linesize[0] + x] = x + y + frame_count * 3; for (int y = 0; y < c->height / 2; y++) { for (int x = 0; x < c->width / 2; x++) { frame->data[1][y * frame->linesize[1] + x] = 128 + y + frame_count * 2; frame->data[2][y * frame->linesize[2] + x] = 64 + x + frame_count * 5; } } /* encode the frame */ av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); if (ret < 0) { std::cerr << "Error encoding video frame" << std::endl; exit(1); } /* if the frame was encoded, write it to the file */ if (got_packet) { pkt.stream_index = st->index; av_packet_rescale_ts(&pkt, time_base, st->time_base); ret = av_interleaved_write_frame(oc, &pkt); if (ret < 0) { std::cerr << "Error while writing video frame" << std::endl; exit(1); } } /* increase the frame count */ frame_count++; /* calculate the next presentation timestamp */ t = (double)frame_count / STREAM_FRAME_RATE; next_pts += (int64_t)(tincr * 1000); if (next_pts > (double)av_gettime()) { av_usleep(next_pts - av_gettime()); } /* free the frame */ av_frame_free(&frame); } /* close the output file and free the format context */ close_output_file(oc); return 0; } ``` 这个代码会生成一个10秒的视频,并在第30帧处进行跳转,继续生成另外10秒的视频。视频中的图像是随机生成的。你可以根据自己的需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值